2007-01-08 10:48:41 +01:00
/*
* ALSA driver for ICEnsemble VT1724 ( Envy24HT )
2008-09-07 01:54:27 +04:00
*
2007-01-08 10:48:41 +01:00
* Lowlevel functions for Ego Sys Waveterminal 192 M
*
* Copyright ( c ) 2006 Guedez Clement < klem . dev @ gmail . com >
* Some functions are taken from the Prodigy192 driver
* source
2008-09-07 01:54:27 +04:00
*
2007-01-08 10:48:41 +01:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2008-09-07 01:54:27 +04:00
*
*/
2007-01-08 10:48:41 +01:00
# include <linux/delay.h>
# include <linux/interrupt.h>
# include <linux/init.h>
# include <sound/core.h>
2015-03-18 02:26:29 +01:00
# include <sound/tlv.h>
2015-03-18 02:26:31 +01:00
# include <linux/slab.h>
2007-01-08 10:48:41 +01:00
# include "ice1712.h"
# include "envy24ht.h"
# include "wtm.h"
# include "stac946x.h"
2015-03-18 02:26:31 +01:00
struct wtm_spec {
/* rate change needs atomic mute/unmute of all dacs*/
struct mutex mute_mutex ;
} ;
2007-01-08 10:48:41 +01:00
/*
2008-09-07 01:54:27 +04:00
* 2 * ADC 6 * DAC no1 ringbuffer r / w on i2c bus
2007-01-08 10:48:41 +01:00
*/
2008-09-07 01:54:27 +04:00
static inline void stac9460_put ( struct snd_ice1712 * ice , int reg ,
2007-01-08 10:48:41 +01:00
unsigned char val )
{
snd_vt1724_write_i2c ( ice , STAC9460_I2C_ADDR , reg , val ) ;
}
static inline unsigned char stac9460_get ( struct snd_ice1712 * ice , int reg )
{
return snd_vt1724_read_i2c ( ice , STAC9460_I2C_ADDR , reg ) ;
}
/*
* 2 * ADC 2 * DAC no2 ringbuffer r / w on i2c bus
*/
static inline void stac9460_2_put ( struct snd_ice1712 * ice , int reg ,
unsigned char val )
{
snd_vt1724_write_i2c ( ice , STAC9460_2_I2C_ADDR , reg , val ) ;
}
static inline unsigned char stac9460_2_get ( struct snd_ice1712 * ice , int reg )
{
return snd_vt1724_read_i2c ( ice , STAC9460_2_I2C_ADDR , reg ) ;
}
/*
* DAC mute control
*/
2015-03-18 02:26:31 +01:00
static void stac9460_dac_mute_all ( struct snd_ice1712 * ice , unsigned char mute ,
unsigned short int * change_mask )
{
unsigned char new , old ;
int id , idx , change ;
/*stac9460 1*/
for ( id = 0 ; id < 7 ; id + + ) {
if ( * change_mask & ( 0x01 < < id ) ) {
if ( id = = 0 )
idx = STAC946X_MASTER_VOLUME ;
else
idx = STAC946X_LF_VOLUME - 1 + id ;
old = stac9460_get ( ice , idx ) ;
new = ( ~ mute < < 7 & 0x80 ) | ( old & ~ 0x80 ) ;
change = ( new ! = old ) ;
if ( change ) {
stac9460_put ( ice , idx , new ) ;
* change_mask = * change_mask | ( 0x01 < < id ) ;
} else {
* change_mask = * change_mask & ~ ( 0x01 < < id ) ;
}
}
}
/*stac9460 2*/
for ( id = 0 ; id < 3 ; id + + ) {
if ( * change_mask & ( 0x01 < < ( id + 7 ) ) ) {
if ( id = = 0 )
idx = STAC946X_MASTER_VOLUME ;
else
idx = STAC946X_LF_VOLUME - 1 + id ;
old = stac9460_2_get ( ice , idx ) ;
new = ( ~ mute < < 7 & 0x80 ) | ( old & ~ 0x80 ) ;
change = ( new ! = old ) ;
if ( change ) {
stac9460_2_put ( ice , idx , new ) ;
* change_mask = * change_mask | ( 0x01 < < id ) ;
} else {
* change_mask = * change_mask & ~ ( 0x01 < < id ) ;
}
}
}
}
2007-07-23 15:42:26 +02:00
# define stac9460_dac_mute_info snd_ctl_boolean_mono_info
2007-01-08 10:48:41 +01:00
static int stac9460_dac_mute_get ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
2015-03-18 02:26:31 +01:00
struct wtm_spec * spec = ice - > spec ;
2007-01-08 10:48:41 +01:00
unsigned char val ;
int idx , id ;
2015-03-18 02:26:31 +01:00
mutex_lock ( & spec - > mute_mutex ) ;
2007-01-08 10:48:41 +01:00
if ( kcontrol - > private_value ) {
idx = STAC946X_MASTER_VOLUME ;
id = 0 ;
} else {
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
idx = id + STAC946X_LF_VOLUME ;
}
if ( id < 6 )
val = stac9460_get ( ice , idx ) ;
2008-09-07 01:54:27 +04:00
else
val = stac9460_2_get ( ice , idx - 6 ) ;
2007-01-08 10:48:41 +01:00
ucontrol - > value . integer . value [ 0 ] = ( ~ val > > 7 ) & 0x1 ;
2015-03-18 02:26:31 +01:00
mutex_unlock ( & spec - > mute_mutex ) ;
2007-01-08 10:48:41 +01:00
return 0 ;
}
static int stac9460_dac_mute_put ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
unsigned char new , old ;
int id , idx ;
int change ;
if ( kcontrol - > private_value ) {
idx = STAC946X_MASTER_VOLUME ;
old = stac9460_get ( ice , idx ) ;
2008-09-07 01:54:27 +04:00
new = ( ~ ucontrol - > value . integer . value [ 0 ] < < 7 & 0x80 ) |
( old & ~ 0x80 ) ;
2007-01-08 10:48:41 +01:00
change = ( new ! = old ) ;
if ( change ) {
stac9460_put ( ice , idx , new ) ;
stac9460_2_put ( ice , idx , new ) ;
}
} else {
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
idx = id + STAC946X_LF_VOLUME ;
if ( id < 6 )
old = stac9460_get ( ice , idx ) ;
2008-09-07 01:54:27 +04:00
else
2007-01-08 10:48:41 +01:00
old = stac9460_2_get ( ice , idx - 6 ) ;
2008-09-07 01:54:27 +04:00
new = ( ~ ucontrol - > value . integer . value [ 0 ] < < 7 & 0x80 ) |
2007-01-08 10:48:41 +01:00
( old & ~ 0x80 ) ;
change = ( new ! = old ) ;
if ( change ) {
if ( id < 6 )
2008-09-07 01:54:27 +04:00
stac9460_put ( ice , idx , new ) ;
2007-01-08 10:48:41 +01:00
else
2008-09-07 01:54:27 +04:00
stac9460_2_put ( ice , idx - 6 , new ) ;
2007-01-08 10:48:41 +01:00
}
}
return change ;
}
/*
* DAC volume attenuation mixer control
*/
static int stac9460_dac_vol_info ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_info * uinfo )
2007-01-08 10:48:41 +01:00
{
uinfo - > type = SNDRV_CTL_ELEM_TYPE_INTEGER ;
uinfo - > count = 1 ;
uinfo - > value . integer . min = 0 ; /* mute */
uinfo - > value . integer . max = 0x7f ; /* 0dB */
return 0 ;
}
static int stac9460_dac_vol_get ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
int idx , id ;
unsigned char vol ;
if ( kcontrol - > private_value ) {
idx = STAC946X_MASTER_VOLUME ;
id = 0 ;
} else {
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
idx = id + STAC946X_LF_VOLUME ;
}
if ( id < 6 )
vol = stac9460_get ( ice , idx ) & 0x7f ;
2008-09-07 01:54:27 +04:00
else
2007-01-08 10:48:41 +01:00
vol = stac9460_2_get ( ice , idx - 6 ) & 0x7f ;
ucontrol - > value . integer . value [ 0 ] = 0x7f - vol ;
return 0 ;
}
static int stac9460_dac_vol_put ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
int idx , id ;
unsigned char tmp , ovol , nvol ;
int change ;
if ( kcontrol - > private_value ) {
idx = STAC946X_MASTER_VOLUME ;
2007-11-15 15:56:07 +01:00
nvol = ucontrol - > value . integer . value [ 0 ] & 0x7f ;
2007-01-08 10:48:41 +01:00
tmp = stac9460_get ( ice , idx ) ;
ovol = 0x7f - ( tmp & 0x7f ) ;
change = ( ovol ! = nvol ) ;
if ( change ) {
2008-09-07 01:54:27 +04:00
stac9460_put ( ice , idx , ( 0x7f - nvol ) | ( tmp & 0x80 ) ) ;
stac9460_2_put ( ice , idx , ( 0x7f - nvol ) | ( tmp & 0x80 ) ) ;
2007-01-08 10:48:41 +01:00
}
} else {
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
idx = id + STAC946X_LF_VOLUME ;
2007-11-15 15:56:07 +01:00
nvol = ucontrol - > value . integer . value [ 0 ] & 0x7f ;
2007-01-08 10:48:41 +01:00
if ( id < 6 )
tmp = stac9460_get ( ice , idx ) ;
2008-09-07 01:54:27 +04:00
else
2007-01-08 10:48:41 +01:00
tmp = stac9460_2_get ( ice , idx - 6 ) ;
ovol = 0x7f - ( tmp & 0x7f ) ;
change = ( ovol ! = nvol ) ;
if ( change ) {
if ( id < 6 )
stac9460_put ( ice , idx , ( 0x7f - nvol ) |
2008-09-07 01:54:27 +04:00
( tmp & 0x80 ) ) ;
else
2007-01-08 10:48:41 +01:00
stac9460_2_put ( ice , idx - 6 , ( 0x7f - nvol ) |
2008-09-07 01:54:27 +04:00
( tmp & 0x80 ) ) ;
2007-01-08 10:48:41 +01:00
}
}
return change ;
}
/*
* ADC mute control
*/
2007-07-23 15:42:26 +02:00
# define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
2007-01-08 10:48:41 +01:00
static int stac9460_adc_mute_get ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
unsigned char val ;
int i , id ;
2008-09-07 01:54:27 +04:00
2007-01-08 10:48:41 +01:00
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
if ( id = = 0 ) {
for ( i = 0 ; i < 2 ; + + i ) {
val = stac9460_get ( ice , STAC946X_MIC_L_VOLUME + i ) ;
ucontrol - > value . integer . value [ i ] = ~ val > > 7 & 0x1 ;
}
} else {
for ( i = 0 ; i < 2 ; + + i ) {
val = stac9460_2_get ( ice , STAC946X_MIC_L_VOLUME + i ) ;
ucontrol - > value . integer . value [ i ] = ~ val > > 7 & 0x1 ;
}
}
return 0 ;
}
static int stac9460_adc_mute_put ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
unsigned char new , old ;
int i , reg , id ;
int change ;
2008-09-07 01:54:27 +04:00
2007-01-08 10:48:41 +01:00
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
if ( id = = 0 ) {
for ( i = 0 ; i < 2 ; + + i ) {
reg = STAC946X_MIC_L_VOLUME + i ;
old = stac9460_get ( ice , reg ) ;
new = ( ~ ucontrol - > value . integer . value [ i ] < < 7 & 0x80 ) |
2008-09-07 01:54:27 +04:00
( old & ~ 0x80 ) ;
2007-01-08 10:48:41 +01:00
change = ( new ! = old ) ;
if ( change )
stac9460_put ( ice , reg , new ) ;
}
} else {
for ( i = 0 ; i < 2 ; + + i ) {
reg = STAC946X_MIC_L_VOLUME + i ;
old = stac9460_2_get ( ice , reg ) ;
new = ( ~ ucontrol - > value . integer . value [ i ] < < 7 & 0x80 ) |
2008-09-07 01:54:27 +04:00
( old & ~ 0x80 ) ;
2007-01-08 10:48:41 +01:00
change = ( new ! = old ) ;
if ( change )
stac9460_2_put ( ice , reg , new ) ;
}
}
return change ;
}
/*
* ADC gain mixer control
*/
static int stac9460_adc_vol_info ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_info * uinfo )
2007-01-08 10:48:41 +01:00
{
uinfo - > type = SNDRV_CTL_ELEM_TYPE_INTEGER ;
uinfo - > count = 2 ;
uinfo - > value . integer . min = 0 ; /* 0dB */
uinfo - > value . integer . max = 0x0f ; /* 22.5dB */
return 0 ;
}
static int stac9460_adc_vol_get ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
int i , reg , id ;
unsigned char vol ;
2008-09-07 01:54:27 +04:00
2007-01-08 10:48:41 +01:00
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
if ( id = = 0 ) {
for ( i = 0 ; i < 2 ; + + i ) {
reg = STAC946X_MIC_L_VOLUME + i ;
vol = stac9460_get ( ice , reg ) & 0x0f ;
ucontrol - > value . integer . value [ i ] = 0x0f - vol ;
}
} else {
for ( i = 0 ; i < 2 ; + + i ) {
reg = STAC946X_MIC_L_VOLUME + i ;
vol = stac9460_2_get ( ice , reg ) & 0x0f ;
ucontrol - > value . integer . value [ i ] = 0x0f - vol ;
}
}
return 0 ;
}
static int stac9460_adc_vol_put ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
int i , reg , id ;
unsigned char ovol , nvol ;
int change ;
2008-09-07 01:54:27 +04:00
2007-01-08 10:48:41 +01:00
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
if ( id = = 0 ) {
for ( i = 0 ; i < 2 ; + + i ) {
reg = STAC946X_MIC_L_VOLUME + i ;
2007-11-15 15:56:07 +01:00
nvol = ucontrol - > value . integer . value [ i ] & 0x0f ;
2007-01-08 10:48:41 +01:00
ovol = 0x0f - stac9460_get ( ice , reg ) ;
change = ( ( ovol & 0x0f ) ! = nvol ) ;
if ( change )
stac9460_put ( ice , reg , ( 0x0f - nvol ) |
2008-09-07 01:54:27 +04:00
( ovol & ~ 0x0f ) ) ;
2007-01-08 10:48:41 +01:00
}
} else {
for ( i = 0 ; i < 2 ; + + i ) {
reg = STAC946X_MIC_L_VOLUME + i ;
2007-11-15 15:56:07 +01:00
nvol = ucontrol - > value . integer . value [ i ] & 0x0f ;
2007-01-08 10:48:41 +01:00
ovol = 0x0f - stac9460_2_get ( ice , reg ) ;
change = ( ( ovol & 0x0f ) ! = nvol ) ;
if ( change )
stac9460_2_put ( ice , reg , ( 0x0f - nvol ) |
2008-09-07 01:54:27 +04:00
( ovol & ~ 0x0f ) ) ;
2007-01-08 10:48:41 +01:00
}
}
return change ;
}
/*
* MIC / LINE switch fonction
*/
2015-03-18 02:26:30 +01:00
static int stac9460_mic_sw_info ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
{
static const char * const texts [ 2 ] = { " Line In " , " Mic " } ;
return snd_ctl_enum_info ( uinfo , 1 , 2 , texts ) ;
}
2007-01-08 10:48:41 +01:00
static int stac9460_mic_sw_get ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
unsigned char val ;
int id ;
2008-09-07 01:54:27 +04:00
2007-01-08 10:48:41 +01:00
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
if ( id = = 0 )
2008-09-07 01:54:27 +04:00
val = stac9460_get ( ice , STAC946X_GENERAL_PURPOSE ) ;
2007-01-08 10:48:41 +01:00
else
2008-09-07 01:54:27 +04:00
val = stac9460_2_get ( ice , STAC946X_GENERAL_PURPOSE ) ;
2015-03-18 02:26:30 +01:00
ucontrol - > value . enumerated . item [ 0 ] = ( val > > 7 ) & 0x1 ;
2007-01-08 10:48:41 +01:00
return 0 ;
}
static int stac9460_mic_sw_put ( struct snd_kcontrol * kcontrol ,
2008-09-07 01:54:27 +04:00
struct snd_ctl_elem_value * ucontrol )
2007-01-08 10:48:41 +01:00
{
struct snd_ice1712 * ice = snd_kcontrol_chip ( kcontrol ) ;
unsigned char new , old ;
int change , id ;
id = snd_ctl_get_ioffidx ( kcontrol , & ucontrol - > id ) ;
if ( id = = 0 )
2008-09-07 01:54:27 +04:00
old = stac9460_get ( ice , STAC946X_GENERAL_PURPOSE ) ;
2007-01-08 10:48:41 +01:00
else
2008-09-07 01:54:27 +04:00
old = stac9460_2_get ( ice , STAC946X_GENERAL_PURPOSE ) ;
2015-03-18 02:26:30 +01:00
new = ( ucontrol - > value . enumerated . item [ 0 ] < < 7 & 0x80 ) | ( old & ~ 0x80 ) ;
2007-01-08 10:48:41 +01:00
change = ( new ! = old ) ;
if ( change ) {
if ( id = = 0 )
2008-09-07 01:54:27 +04:00
stac9460_put ( ice , STAC946X_GENERAL_PURPOSE , new ) ;
2007-01-08 10:48:41 +01:00
else
2008-09-07 01:54:27 +04:00
stac9460_2_put ( ice , STAC946X_GENERAL_PURPOSE , new ) ;
2007-01-08 10:48:41 +01:00
}
return change ;
}
2015-03-18 02:26:29 +01:00
2015-03-18 02:26:31 +01:00
/*
* Handler for setting correct codec rate - called when rate change is detected
*/
static void stac9460_set_rate_val ( struct snd_ice1712 * ice , unsigned int rate )
{
unsigned char old , new ;
unsigned short int changed ;
struct wtm_spec * spec = ice - > spec ;
if ( rate = = 0 ) /* no hint - S/PDIF input is master, simply return */
return ;
else if ( rate < = 48000 )
new = 0x08 ; /* 256x, base rate mode */
else if ( rate < = 96000 )
new = 0x11 ; /* 256x, mid rate mode */
else
new = 0x12 ; /* 128x, high rate mode */
old = stac9460_get ( ice , STAC946X_MASTER_CLOCKING ) ;
if ( old = = new )
return ;
/* change detected, setting master clock, muting first */
/* due to possible conflicts with mute controls - mutexing */
mutex_lock ( & spec - > mute_mutex ) ;
/* we have to remember current mute status for each DAC */
changed = 0xFFFF ;
stac9460_dac_mute_all ( ice , 0 , & changed ) ;
/*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/
stac9460_put ( ice , STAC946X_MASTER_CLOCKING , new ) ;
stac9460_2_put ( ice , STAC946X_MASTER_CLOCKING , new ) ;
udelay ( 10 ) ;
/* unmuting - only originally unmuted dacs -
* i . e . those changed when muting */
stac9460_dac_mute_all ( ice , 1 , & changed ) ;
mutex_unlock ( & spec - > mute_mutex ) ;
}
2015-03-18 02:26:29 +01:00
/*Limits value in dB for fader*/
static const DECLARE_TLV_DB_SCALE ( db_scale_dac , - 19125 , 75 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( db_scale_adc , 0 , 150 , 0 ) ;
2007-01-08 10:48:41 +01:00
/*
* Control tabs
*/
2012-12-06 12:35:10 -05:00
static struct snd_kcontrol_new stac9640_controls [ ] = {
2007-01-08 10:48:41 +01:00
{
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
2015-03-18 02:26:29 +01:00
. access = ( SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ ) ,
2007-01-08 10:48:41 +01:00
. name = " Master Playback Switch " ,
. info = stac9460_dac_mute_info ,
. get = stac9460_dac_mute_get ,
. put = stac9460_dac_mute_put ,
2015-03-18 02:26:29 +01:00
. private_value = 1 ,
. tlv = { . p = db_scale_dac }
2007-01-08 10:48:41 +01:00
} ,
{
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
. name = " Master Playback Volume " ,
. info = stac9460_dac_vol_info ,
. get = stac9460_dac_vol_get ,
. put = stac9460_dac_vol_put ,
. private_value = 1 ,
} ,
{
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
2015-03-18 02:26:30 +01:00
. name = " MIC/Line Input Enum " ,
2007-01-08 10:48:41 +01:00
. count = 2 ,
. info = stac9460_mic_sw_info ,
. get = stac9460_mic_sw_get ,
. put = stac9460_mic_sw_put ,
} ,
{
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
. name = " DAC Switch " ,
. count = 8 ,
. info = stac9460_dac_mute_info ,
. get = stac9460_dac_mute_get ,
. put = stac9460_dac_mute_put ,
} ,
{
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
2015-03-18 02:26:29 +01:00
. access = ( SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ ) ,
2007-01-08 10:48:41 +01:00
. name = " DAC Volume " ,
. count = 8 ,
. info = stac9460_dac_vol_info ,
. get = stac9460_dac_vol_get ,
. put = stac9460_dac_vol_put ,
2015-03-18 02:26:29 +01:00
. tlv = { . p = db_scale_dac }
2007-01-08 10:48:41 +01:00
} ,
{
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
. name = " ADC Switch " ,
. count = 2 ,
. info = stac9460_adc_mute_info ,
. get = stac9460_adc_mute_get ,
. put = stac9460_adc_mute_put ,
} ,
{
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
2015-03-18 02:26:29 +01:00
. access = ( SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ ) ,
2007-01-08 10:48:41 +01:00
. name = " ADC Volume " ,
. count = 2 ,
. info = stac9460_adc_vol_info ,
. get = stac9460_adc_vol_get ,
. put = stac9460_adc_vol_put ,
2015-03-18 02:26:29 +01:00
. tlv = { . p = db_scale_adc }
2008-09-07 01:54:27 +04:00
}
2007-01-08 10:48:41 +01:00
} ;
/*INIT*/
2012-12-06 12:35:10 -05:00
static int wtm_add_controls ( struct snd_ice1712 * ice )
2007-01-08 10:48:41 +01:00
{
unsigned int i ;
int err ;
for ( i = 0 ; i < ARRAY_SIZE ( stac9640_controls ) ; i + + ) {
err = snd_ctl_add ( ice - > card ,
snd_ctl_new1 ( & stac9640_controls [ i ] , ice ) ) ;
if ( err < 0 )
return err ;
}
return 0 ;
}
2012-12-06 12:35:10 -05:00
static int wtm_init ( struct snd_ice1712 * ice )
2007-01-08 10:48:41 +01:00
{
2015-03-18 02:26:26 +01:00
static unsigned short stac_inits_wtm [ ] = {
2007-01-08 10:48:41 +01:00
STAC946X_RESET , 0 ,
2015-03-18 02:26:31 +01:00
STAC946X_MASTER_CLOCKING , 0x11 ,
2007-01-08 10:48:41 +01:00
( unsigned short ) - 1
} ;
unsigned short * p ;
2015-03-18 02:26:31 +01:00
struct wtm_spec * spec ;
2008-09-07 01:54:27 +04:00
2007-01-08 10:48:41 +01:00
/*WTM 192M*/
ice - > num_total_dacs = 8 ;
ice - > num_total_adcs = 4 ;
ice - > force_rdma1 = 1 ;
2015-03-18 02:26:31 +01:00
/*init mutex for dac mute conflict*/
spec = kzalloc ( sizeof ( * spec ) , GFP_KERNEL ) ;
if ( ! spec )
return - ENOMEM ;
ice - > spec = spec ;
mutex_init ( & spec - > mute_mutex ) ;
2007-01-08 10:48:41 +01:00
/*initialize codec*/
2015-03-18 02:26:26 +01:00
p = stac_inits_wtm ;
2007-01-08 10:48:41 +01:00
for ( ; * p ! = ( unsigned short ) - 1 ; p + = 2 ) {
stac9460_put ( ice , p [ 0 ] , p [ 1 ] ) ;
stac9460_2_put ( ice , p [ 0 ] , p [ 1 ] ) ;
}
2015-03-18 02:26:31 +01:00
ice - > gpio . set_pro_rate = stac9460_set_rate_val ;
2007-01-08 10:48:41 +01:00
return 0 ;
}
2012-12-06 12:35:10 -05:00
static unsigned char wtm_eeprom [ ] = {
2015-03-18 02:26:28 +01:00
[ ICE_EEP2_SYSCONF ] = 0x67 , /*SYSCONF: clock 192KHz, mpu401,
4 ADC , 8 DAC */
2015-03-18 02:26:27 +01:00
[ ICE_EEP2_ACLINK ] = 0x80 , /* ACLINK : I2S */
[ ICE_EEP2_I2S ] = 0xf8 , /* I2S: vol; 96k, 24bit, 192k */
[ ICE_EEP2_SPDIF ] = 0xc1 , /*SPDIF: out-en, spidf ext out*/
[ ICE_EEP2_GPIO_DIR ] = 0x9f ,
[ ICE_EEP2_GPIO_DIR1 ] = 0xff ,
[ ICE_EEP2_GPIO_DIR2 ] = 0x7f ,
[ ICE_EEP2_GPIO_MASK ] = 0x9f ,
[ ICE_EEP2_GPIO_MASK1 ] = 0xff ,
[ ICE_EEP2_GPIO_MASK2 ] = 0x7f ,
[ ICE_EEP2_GPIO_STATE ] = 0x16 ,
[ ICE_EEP2_GPIO_STATE1 ] = 0x80 ,
[ ICE_EEP2_GPIO_STATE2 ] = 0x00 ,
2007-01-08 10:48:41 +01:00
} ;
/*entry point*/
2012-12-06 12:35:10 -05:00
struct snd_ice1712_card_info snd_vt1724_wtm_cards [ ] = {
2007-01-08 10:48:41 +01:00
{
. subvendor = VT1724_SUBDEVICE_WTM ,
. name = " ESI Waveterminal 192M " ,
. model = " WT192M " ,
. chip_init = wtm_init ,
. build_controls = wtm_add_controls ,
. eeprom_size = sizeof ( wtm_eeprom ) ,
. eeprom_data = wtm_eeprom ,
} ,
{ } /*terminator*/
} ;