2005-04-16 15:20:36 -07:00
/*
* Universal Interface for Intel High Definition Audio Codec
*
* Local helper functions
*
* Copyright ( c ) 2004 Takashi Iwai < tiwai @ suse . de >
*
* 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 .
*/
# ifndef __SOUND_HDA_LOCAL_H
# define __SOUND_HDA_LOCAL_H
2009-11-16 11:25:33 +01:00
/* We abuse kcontrol_new.subdev field to pass the NID corresponding to
* the given new control . If id . subdev has a bit flag HDA_SUBDEV_NID_FLAG ,
* snd_hda_ctl_add ( ) takes the lower - bit subdev value as a valid NID .
*
* Note that the subdevice field is cleared again before the real registration
* in snd_hda_ctl_add ( ) , so that this value won ' t appear in the outside .
*/
# define HDA_SUBDEV_NID_FLAG (1U << 31)
ALSA: hda - introduce HDA_SUBDEV_AMP_FLAG (ControlAmp in proc)
The purpose of this changeset is to show information about amplifier
setting in the codec proc file. Something like:
Control: name="Front Playback Volume", index=0, device=0
ControlAmp: chs=3, dir=Out, idx=0, ofs=0
Control: name="Front Playback Switch", index=0, device=0
ControlAmp: chs=3, dir=In, idx=2, ofs=0
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
2009-12-08 17:45:25 +01:00
# define HDA_SUBDEV_AMP_FLAG (1U << 30)
2009-11-16 11:25:33 +01:00
2005-04-16 15:20:36 -07:00
/*
* for mixer controls
*/
2009-01-20 13:07:55 +01:00
# define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \
( ( nid ) | ( ( chs ) < < 16 ) | ( ( dir ) < < 18 ) | ( ( idx ) < < 19 ) | ( ( ofs ) < < 23 ) )
2010-10-15 10:32:50 +02:00
# define HDA_AMP_VAL_MIN_MUTE (1<<29)
2007-07-27 16:52:19 +02:00
# define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
2009-01-20 13:07:55 +01:00
HDA_COMPOSE_AMP_VAL_OFS ( nid , chs , idx , dir , 0 )
2005-11-02 18:26:49 +01:00
/* mono volume with index (index=0,1,...) (channel=1,2) */
2010-10-15 10:32:50 +02:00
# define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, dir, flags) \
2005-04-16 15:20:36 -07:00
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , . index = xcidx , \
2009-12-10 13:57:01 +01:00
. subdevice = HDA_SUBDEV_AMP_FLAG , \
2006-07-05 17:39:49 +02:00
. access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK , \
2005-04-16 15:20:36 -07:00
. info = snd_hda_mixer_amp_volume_info , \
. get = snd_hda_mixer_amp_volume_get , \
. put = snd_hda_mixer_amp_volume_put , \
2006-08-17 16:23:07 +02:00
. tlv = { . c = snd_hda_mixer_amp_tlv } , \
2010-10-15 10:32:50 +02:00
. private_value = HDA_COMPOSE_AMP_VAL ( nid , channel , xindex , dir ) | flags }
2005-11-02 18:26:49 +01:00
/* stereo volume with index */
2005-04-16 15:20:36 -07:00
# define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \
2010-10-15 10:32:50 +02:00
HDA_CODEC_VOLUME_MONO_IDX ( xname , xcidx , nid , 3 , xindex , direction , 0 )
2005-11-02 18:26:49 +01:00
/* mono volume */
2005-04-16 15:20:36 -07:00
# define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \
2010-10-15 10:32:50 +02:00
HDA_CODEC_VOLUME_MONO_IDX ( xname , 0 , nid , channel , xindex , direction , 0 )
2005-11-02 18:26:49 +01:00
/* stereo volume */
2005-04-16 15:20:36 -07:00
# define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \
HDA_CODEC_VOLUME_MONO ( xname , nid , 3 , xindex , direction )
2010-10-15 10:32:50 +02:00
/* stereo volume with min=mute */
# define HDA_CODEC_VOLUME_MIN_MUTE(xname, nid, xindex, direction) \
HDA_CODEC_VOLUME_MONO_IDX ( xname , 0 , nid , 3 , xindex , direction , \
HDA_AMP_VAL_MIN_MUTE )
2005-11-02 18:26:49 +01:00
/* mono mute switch with index (index=0,1,...) (channel=1,2) */
2005-04-16 15:20:36 -07:00
# define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , . index = xcidx , \
2009-12-10 13:57:01 +01:00
. subdevice = HDA_SUBDEV_AMP_FLAG , \
2005-04-16 15:20:36 -07:00
. info = snd_hda_mixer_amp_switch_info , \
. get = snd_hda_mixer_amp_switch_get , \
. put = snd_hda_mixer_amp_switch_put , \
. private_value = HDA_COMPOSE_AMP_VAL ( nid , channel , xindex , direction ) }
2005-11-02 18:26:49 +01:00
/* stereo mute switch with index */
2005-04-16 15:20:36 -07:00
# define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \
HDA_CODEC_MUTE_MONO_IDX ( xname , xcidx , nid , 3 , xindex , direction )
2005-11-02 18:26:49 +01:00
/* mono mute switch */
2005-04-16 15:20:36 -07:00
# define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \
HDA_CODEC_MUTE_MONO_IDX ( xname , 0 , nid , channel , xindex , direction )
2005-11-02 18:26:49 +01:00
/* stereo mute switch */
2005-04-16 15:20:36 -07:00
# define HDA_CODEC_MUTE(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_MONO ( xname , nid , 3 , xindex , direction )
2009-11-16 15:35:59 +01:00
# ifdef CONFIG_SND_HDA_INPUT_BEEP
2009-10-21 14:48:23 +02:00
/* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */
# define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , . index = xcidx , \
2009-12-10 13:57:01 +01:00
. subdevice = HDA_SUBDEV_AMP_FLAG , \
2009-10-21 14:48:23 +02:00
. info = snd_hda_mixer_amp_switch_info , \
2012-07-03 17:27:57 +02:00
. get = snd_hda_mixer_amp_switch_get_beep , \
2009-10-21 14:48:23 +02:00
. put = snd_hda_mixer_amp_switch_put_beep , \
. private_value = HDA_COMPOSE_AMP_VAL ( nid , channel , xindex , direction ) }
2009-11-16 15:35:59 +01:00
# else
/* no digital beep - just the standard one */
# define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, ch, xidx, dir) \
HDA_CODEC_MUTE_MONO_IDX ( xname , xcidx , nid , ch , xidx , dir )
# endif /* CONFIG_SND_HDA_INPUT_BEEP */
2009-10-21 14:48:23 +02:00
/* special beep mono mute switch */
# define HDA_CODEC_MUTE_BEEP_MONO(xname, nid, channel, xindex, direction) \
HDA_CODEC_MUTE_BEEP_MONO_IDX ( xname , 0 , nid , channel , xindex , direction )
/* special beep stereo mute switch */
# define HDA_CODEC_MUTE_BEEP(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_BEEP_MONO ( xname , nid , 3 , xindex , direction )
2005-04-16 15:20:36 -07:00
2009-11-11 13:49:07 +01:00
extern const char * snd_hda_pcm_type_name [ ] ;
2007-07-27 16:52:19 +02:00
int snd_hda_mixer_amp_volume_info ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_hda_mixer_amp_volume_get ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_hda_mixer_amp_volume_put ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_hda_mixer_amp_tlv ( struct snd_kcontrol * kcontrol , int op_flag ,
unsigned int size , unsigned int __user * tlv ) ;
int snd_hda_mixer_amp_switch_info ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_hda_mixer_amp_switch_get ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_hda_mixer_amp_switch_put ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
2009-11-16 15:35:59 +01:00
# ifdef CONFIG_SND_HDA_INPUT_BEEP
2012-07-03 17:27:57 +02:00
int snd_hda_mixer_amp_switch_get_beep ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
2009-10-21 14:48:23 +02:00
int snd_hda_mixer_amp_switch_put_beep ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
2009-11-16 15:35:59 +01:00
# endif
2006-03-01 14:16:17 +01:00
/* lowlevel accessor with caching; use carefully */
2015-02-25 15:18:50 +01:00
# define snd_hda_codec_amp_read(codec, nid, ch, dir, idx) \
snd_hdac_regmap_get_amp ( & ( codec ) - > core , nid , ch , dir , idx )
# define snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val) \
snd_hdac_regmap_update_amp ( & ( codec ) - > core , nid , ch , dir , idx , mask , val )
2007-08-10 17:11:07 +02:00
int snd_hda_codec_amp_stereo ( struct hda_codec * codec , hda_nid_t nid ,
int dir , int idx , int mask , int val ) ;
2012-12-14 10:32:21 +01:00
int snd_hda_codec_amp_init ( struct hda_codec * codec , hda_nid_t nid , int ch ,
int direction , int idx , int mask , int val ) ;
int snd_hda_codec_amp_init_stereo ( struct hda_codec * codec , hda_nid_t nid ,
int dir , int idx , int mask , int val ) ;
2008-01-10 16:53:55 +01:00
void snd_hda_set_vmaster_tlv ( struct hda_codec * codec , hda_nid_t nid , int dir ,
unsigned int * tlv ) ;
struct snd_kcontrol * snd_hda_find_mixer_ctl ( struct hda_codec * codec ,
const char * name ) ;
2012-03-09 17:51:10 +01:00
int __snd_hda_add_vmaster ( struct hda_codec * codec , char * name ,
2012-03-12 12:25:03 +01:00
unsigned int * tlv , const char * const * slaves ,
const char * suffix , bool init_slave_vol ,
struct snd_kcontrol * * ctl_ret ) ;
2012-03-09 17:51:10 +01:00
# define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \
2012-03-12 12:25:03 +01:00
__snd_hda_add_vmaster ( codec , name , tlv , slaves , suffix , true , NULL )
2009-02-23 16:57:04 +01:00
int snd_hda_codec_reset ( struct hda_codec * codec ) ;
2015-03-03 17:22:12 +01:00
void snd_hda_codec_register ( struct hda_codec * codec ) ;
2015-02-27 18:17:28 +01:00
void snd_hda_codec_cleanup_for_unbind ( struct hda_codec * codec ) ;
2008-01-10 16:53:55 +01:00
2012-03-12 16:59:58 +01:00
enum {
HDA_VMUTE_OFF ,
HDA_VMUTE_ON ,
HDA_VMUTE_FOLLOW_MASTER ,
} ;
struct hda_vmaster_mute_hook {
/* below two fields must be filled by the caller of
* snd_hda_add_vmaster_hook ( ) beforehand
*/
struct snd_kcontrol * sw_kctl ;
void ( * hook ) ( void * , int ) ;
/* below are initialized automatically */
unsigned int mute_mode ; /* HDA_VMUTE_XXX */
struct hda_codec * codec ;
} ;
int snd_hda_add_vmaster_hook ( struct hda_codec * codec ,
2012-03-13 07:55:10 +01:00
struct hda_vmaster_mute_hook * hook ,
bool expose_enum_ctl ) ;
2012-03-12 16:59:58 +01:00
void snd_hda_sync_vmaster_hook ( struct hda_vmaster_mute_hook * hook ) ;
2007-08-10 17:11:07 +02:00
/* amp value bits */
# define HDA_AMP_MUTE 0x80
# define HDA_AMP_UNMUTE 0x00
# define HDA_AMP_VOLMASK 0x7f
2005-11-02 18:26:49 +01:00
/* mono switch binding multiple inputs */
# define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , . index = 0 , \
. info = snd_hda_mixer_amp_switch_info , \
. get = snd_hda_mixer_bind_switch_get , \
. put = snd_hda_mixer_bind_switch_put , \
. private_value = HDA_COMPOSE_AMP_VAL ( nid , channel , indices , direction ) }
/* stereo switch binding multiple inputs */
2007-07-27 16:52:19 +02:00
# define HDA_BIND_MUTE(xname,nid,indices,dir) \
HDA_BIND_MUTE_MONO ( xname , nid , 3 , indices , dir )
2005-11-02 18:26:49 +01:00
2007-07-27 16:52:19 +02:00
int snd_hda_mixer_bind_switch_get ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_hda_mixer_bind_switch_put ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
2005-11-02 18:26:49 +01:00
2007-07-27 19:02:40 +02:00
/* more generic bound controls */
struct hda_ctl_ops {
snd_kcontrol_info_t * info ;
snd_kcontrol_get_t * get ;
snd_kcontrol_put_t * put ;
snd_kcontrol_tlv_rw_t * tlv ;
} ;
extern struct hda_ctl_ops snd_hda_bind_vol ; /* for bind-volume with TLV */
extern struct hda_ctl_ops snd_hda_bind_sw ; /* for bind-switch */
struct hda_bind_ctls {
struct hda_ctl_ops * ops ;
2009-02-25 22:28:45 +01:00
unsigned long values [ ] ;
2007-07-27 19:02:40 +02:00
} ;
int snd_hda_mixer_bind_ctls_info ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_hda_mixer_bind_ctls_get ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_hda_mixer_bind_ctls_put ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_hda_mixer_bind_tlv ( struct snd_kcontrol * kcontrol , int op_flag ,
unsigned int size , unsigned int __user * tlv ) ;
# define HDA_BIND_VOL(xname, bindrec) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , \
. name = xname , \
. access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK , \
. info = snd_hda_mixer_bind_ctls_info , \
. get = snd_hda_mixer_bind_ctls_get , \
. put = snd_hda_mixer_bind_ctls_put , \
. tlv = { . c = snd_hda_mixer_bind_tlv } , \
. private_value = ( long ) ( bindrec ) }
# define HDA_BIND_SW(xname, bindrec) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , \
. name = xname , \
. info = snd_hda_mixer_bind_ctls_info , \
. get = snd_hda_mixer_bind_ctls_get , \
. put = snd_hda_mixer_bind_ctls_put , \
. private_value = ( long ) ( bindrec ) }
/*
* SPDIF I / O
*/
2012-10-12 17:24:51 +02:00
int snd_hda_create_dig_out_ctls ( struct hda_codec * codec ,
hda_nid_t associated_nid ,
hda_nid_t cvt_nid , int type ) ;
# define snd_hda_create_spdif_out_ctls(codec, anid, cnid) \
snd_hda_create_dig_out_ctls ( codec , anid , cnid , HDA_PCM_TYPE_SPDIF )
2005-04-16 15:20:36 -07:00
int snd_hda_create_spdif_in_ctls ( struct hda_codec * codec , hda_nid_t nid ) ;
/*
* input MUX helper
*/
2005-11-21 16:33:22 +01:00
# define HDA_MAX_NUM_INPUTS 16
2005-04-16 15:20:36 -07:00
struct hda_input_mux_item {
2010-09-09 14:21:17 +02:00
char label [ 32 ] ;
2005-04-16 15:20:36 -07:00
unsigned int index ;
} ;
struct hda_input_mux {
unsigned int num_items ;
struct hda_input_mux_item items [ HDA_MAX_NUM_INPUTS ] ;
} ;
2007-07-27 16:52:19 +02:00
int snd_hda_input_mux_info ( const struct hda_input_mux * imux ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_hda_input_mux_put ( struct hda_codec * codec ,
const struct hda_input_mux * imux ,
2005-11-17 14:57:47 +01:00
struct snd_ctl_elem_value * ucontrol , hda_nid_t nid ,
2005-04-16 15:20:36 -07:00
unsigned int * cur_val ) ;
2014-06-06 18:12:16 +02:00
int snd_hda_add_imux_item ( struct hda_codec * codec ,
struct hda_input_mux * imux , const char * label ,
2012-05-07 17:42:31 +02:00
int index , int * type_index_ret ) ;
2005-04-16 15:20:36 -07:00
/*
* Multi - channel / digital - out PCM helper
*/
enum { HDA_FRONT , HDA_REAR , HDA_CLFE , HDA_SIDE } ; /* index for dac_nidx */
enum { HDA_DIG_NONE , HDA_DIG_EXCLUSIVE , HDA_DIG_ANALOG_DUP } ; /* dig_out_used */
2011-08-23 18:16:13 +02:00
# define HDA_MAX_OUTS 5
2005-04-16 15:20:36 -07:00
struct hda_multi_out {
int num_dacs ; /* # of DACs, must be more than 1 */
2011-05-02 11:29:30 +02:00
const hda_nid_t * dac_nids ; /* DAC list */
2005-04-16 15:20:36 -07:00
hda_nid_t hp_nid ; /* optional DAC for HP, 0 when not exists */
2011-08-23 18:16:13 +02:00
hda_nid_t hp_out_nid [ HDA_MAX_OUTS ] ; /* DACs for multiple HPs */
hda_nid_t extra_out_nid [ HDA_MAX_OUTS ] ; /* other (e.g. speaker) DACs */
2005-04-16 15:20:36 -07:00
hda_nid_t dig_out_nid ; /* digital out audio widget */
2011-05-02 11:29:30 +02:00
const hda_nid_t * slave_dig_outs ;
2005-04-16 15:20:36 -07:00
int max_channels ; /* currently supported analog channels */
int dig_out_used ; /* current usage of digital out (HDA_DIG_XXX) */
2007-10-26 12:35:56 +02:00
int no_share_stream ; /* don't share a stream with multiple pins */
2008-02-12 18:37:26 +01:00
int share_spdif ; /* share SPDIF pin */
/* PCM information for both analog and SPDIF DACs */
unsigned int analog_rates ;
unsigned int analog_maxbps ;
u64 analog_formats ;
unsigned int spdif_rates ;
unsigned int spdif_maxbps ;
u64 spdif_formats ;
2005-04-16 15:20:36 -07:00
} ;
2008-02-12 18:37:26 +01:00
int snd_hda_create_spdif_share_sw ( struct hda_codec * codec ,
struct hda_multi_out * mout ) ;
2007-07-27 16:52:19 +02:00
int snd_hda_multi_out_dig_open ( struct hda_codec * codec ,
struct hda_multi_out * mout ) ;
int snd_hda_multi_out_dig_close ( struct hda_codec * codec ,
struct hda_multi_out * mout ) ;
2007-04-05 14:51:48 +02:00
int snd_hda_multi_out_dig_prepare ( struct hda_codec * codec ,
struct hda_multi_out * mout ,
unsigned int stream_tag ,
unsigned int format ,
struct snd_pcm_substream * substream ) ;
2009-02-13 11:32:28 +01:00
int snd_hda_multi_out_dig_cleanup ( struct hda_codec * codec ,
struct hda_multi_out * mout ) ;
2007-07-27 16:52:19 +02:00
int snd_hda_multi_out_analog_open ( struct hda_codec * codec ,
struct hda_multi_out * mout ,
2008-02-12 18:37:26 +01:00
struct snd_pcm_substream * substream ,
struct hda_pcm_stream * hinfo ) ;
2007-07-27 16:52:19 +02:00
int snd_hda_multi_out_analog_prepare ( struct hda_codec * codec ,
struct hda_multi_out * mout ,
2005-04-16 15:20:36 -07:00
unsigned int stream_tag ,
unsigned int format ,
2005-11-17 14:57:47 +01:00
struct snd_pcm_substream * substream ) ;
2007-07-27 16:52:19 +02:00
int snd_hda_multi_out_analog_cleanup ( struct hda_codec * codec ,
struct hda_multi_out * mout ) ;
2005-04-16 15:20:36 -07:00
/*
* generic proc interface
*/
2015-05-27 19:45:45 +08:00
# ifdef CONFIG_SND_PROC_FS
2005-04-16 15:20:36 -07:00
int snd_hda_codec_proc_new ( struct hda_codec * codec ) ;
# else
static inline int snd_hda_codec_proc_new ( struct hda_codec * codec ) { return 0 ; }
# endif
2008-11-19 15:14:02 +08:00
# define SND_PRINT_BITS_ADVISED_BUFSIZE 16
void snd_print_pcm_bits ( int pcm , char * buf , int buflen ) ;
2005-04-16 15:20:36 -07:00
/*
* Misc
*/
2007-07-27 16:52:19 +02:00
int snd_hda_add_new_ctls ( struct hda_codec * codec ,
2011-05-02 11:29:30 +02:00
const struct snd_kcontrol_new * knew ) ;
2005-04-16 15:20:36 -07:00
2012-12-18 18:12:44 +01:00
/*
* Fix - up pin default configurations and add default verbs
*/
struct hda_pintbl {
hda_nid_t nid ;
u32 val ;
} ;
struct hda_model_fixup {
const int id ;
const char * name ;
} ;
struct hda_fixup {
int type ;
2013-01-23 18:10:10 +01:00
bool chained : 1 ; /* call the chained fixup(s) after this */
bool chained_before : 1 ; /* call the chained fixup(s) before this */
2012-12-18 18:12:44 +01:00
int chain_id ;
union {
const struct hda_pintbl * pins ;
const struct hda_verb * verbs ;
void ( * func ) ( struct hda_codec * codec ,
const struct hda_fixup * fix ,
int action ) ;
} v ;
} ;
2014-05-26 16:22:41 +08:00
struct snd_hda_pin_quirk {
unsigned int codec ; /* Codec vendor/device ID */
unsigned short subvendor ; /* PCI subvendor ID */
const struct hda_pintbl * pins ; /* list of matching pins */
# ifdef CONFIG_SND_DEBUG_VERBOSE
const char * name ;
# endif
int value ; /* quirk value */
} ;
2014-06-24 14:46:53 +02:00
# ifdef CONFIG_SND_DEBUG_VERBOSE
# define SND_HDA_PIN_QUIRK(_codec, _subvendor, _name, _value, _pins...) \
{ . codec = _codec , \
. subvendor = _subvendor , \
. name = _name , \
. value = _value , \
2014-10-24 10:00:38 +02:00
. pins = ( const struct hda_pintbl [ ] ) { _pins , { 0 , 0 } } \
2014-06-24 14:46:53 +02:00
}
# else
# define SND_HDA_PIN_QUIRK(_codec, _subvendor, _name, _value, _pins...) \
{ . codec = _codec , \
. subvendor = _subvendor , \
. value = _value , \
2014-10-24 10:00:38 +02:00
. pins = ( const struct hda_pintbl [ ] ) { _pins , { 0 , 0 } } \
2014-06-24 14:46:53 +02:00
}
# endif
2014-07-22 14:09:34 +02:00
# define HDA_FIXUP_ID_NOT_SET -1
# define HDA_FIXUP_ID_NO_FIXUP -2
2014-06-24 14:46:53 +02:00
2012-12-18 18:12:44 +01:00
/* fixup types */
enum {
HDA_FIXUP_INVALID ,
HDA_FIXUP_PINS ,
HDA_FIXUP_VERBS ,
HDA_FIXUP_FUNC ,
2013-01-10 10:18:14 +01:00
HDA_FIXUP_PINCTLS ,
2012-12-18 18:12:44 +01:00
} ;
/* fixup action definitions */
enum {
HDA_FIXUP_ACT_PRE_PROBE ,
HDA_FIXUP_ACT_PROBE ,
HDA_FIXUP_ACT_INIT ,
HDA_FIXUP_ACT_BUILD ,
2013-10-16 23:10:32 +02:00
HDA_FIXUP_ACT_FREE ,
2012-12-18 18:12:44 +01:00
} ;
int snd_hda_add_verbs ( struct hda_codec * codec , const struct hda_verb * list ) ;
void snd_hda_apply_verbs ( struct hda_codec * codec ) ;
void snd_hda_apply_pincfgs ( struct hda_codec * codec ,
const struct hda_pintbl * cfg ) ;
void snd_hda_apply_fixup ( struct hda_codec * codec , int action ) ;
void snd_hda_pick_fixup ( struct hda_codec * codec ,
const struct hda_model_fixup * models ,
const struct snd_pci_quirk * quirk ,
const struct hda_fixup * fixlist ) ;
2014-05-26 16:22:41 +08:00
void snd_hda_pick_pin_fixup ( struct hda_codec * codec ,
const struct snd_hda_pin_quirk * pin_quirk ,
const struct hda_fixup * fixlist ) ;
2012-05-07 17:42:31 +02:00
/* helper macros to retrieve pin default-config values */
2007-07-27 16:52:19 +02:00
# define get_defcfg_connect(cfg) \
( ( cfg & AC_DEFCFG_PORT_CONN ) > > AC_DEFCFG_PORT_CONN_SHIFT )
# define get_defcfg_association(cfg) \
( ( cfg & AC_DEFCFG_DEF_ASSOC ) > > AC_DEFCFG_ASSOC_SHIFT )
# define get_defcfg_location(cfg) \
( ( cfg & AC_DEFCFG_LOCATION ) > > AC_DEFCFG_LOCATION_SHIFT )
# define get_defcfg_sequence(cfg) \
( cfg & AC_DEFCFG_SEQUENCE )
# define get_defcfg_device(cfg) \
( ( cfg & AC_DEFCFG_DEVICE ) > > AC_DEFCFG_DEVICE_SHIFT )
2011-11-02 07:44:11 +01:00
# define get_defcfg_misc(cfg) \
( ( cfg & AC_DEFCFG_MISC ) > > AC_DEFCFG_MISC_SHIFT )
2007-07-27 16:52:19 +02:00
2005-11-17 11:09:23 +01:00
/* amp values */
# define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
# define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
2008-10-29 08:15:30 +01:00
# define AMP_OUT_MUTE 0xb080
# define AMP_OUT_UNMUTE 0xb000
# define AMP_OUT_ZERO 0xb000
2005-11-17 11:09:23 +01:00
/* pinctl values */
2008-09-13 16:54:59 -07:00
# define PIN_IN (AC_PINCTL_IN_EN)
2008-10-29 08:15:30 +01:00
# define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ)
2008-09-13 16:54:59 -07:00
# define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50)
2008-10-29 08:15:30 +01:00
# define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD)
2008-09-13 16:54:59 -07:00
# define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80)
2008-10-29 08:15:30 +01:00
# define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100)
# define PIN_OUT (AC_PINCTL_OUT_EN)
2008-09-13 16:54:59 -07:00
# define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
# define PIN_HP_AMP (AC_PINCTL_HP_EN)
2005-11-17 11:09:23 +01:00
2012-04-20 13:06:53 +02:00
unsigned int snd_hda_get_default_vref ( struct hda_codec * codec , hda_nid_t pin ) ;
2013-01-10 08:56:46 +01:00
unsigned int snd_hda_correct_pin_ctl ( struct hda_codec * codec ,
hda_nid_t pin , unsigned int val ) ;
2012-04-20 12:34:50 +02:00
int _snd_hda_set_pin_ctl ( struct hda_codec * codec , hda_nid_t pin ,
unsigned int val , bool cached ) ;
/**
* _snd_hda_set_pin_ctl - Set a pin - control value safely
* @ codec : the codec instance
* @ pin : the pin NID to set the control
* @ val : the pin - control value ( AC_PINCTL_ * bits )
*
* This function sets the pin - control value to the given pin , but
* filters out the invalid pin - control bits when the pin has no such
* capabilities . For example , when PIN_HP is passed but the pin has no
* HP - drive capability , the HP bit is omitted .
*
* The function doesn ' t check the input VREF capability bits , though .
2012-04-20 13:06:53 +02:00
* Use snd_hda_get_default_vref ( ) to guess the right value .
2012-04-20 12:34:50 +02:00
* Also , this function is only for analog pins , not for HDMI pins .
*/
static inline int
snd_hda_set_pin_ctl ( struct hda_codec * codec , hda_nid_t pin , unsigned int val )
{
return _snd_hda_set_pin_ctl ( codec , pin , val , false ) ;
}
/**
* snd_hda_set_pin_ctl_cache - Set a pin - control value safely
* @ codec : the codec instance
* @ pin : the pin NID to set the control
* @ val : the pin - control value ( AC_PINCTL_ * bits )
*
* Just like snd_hda_set_pin_ctl ( ) but write to cache as well .
*/
static inline int
snd_hda_set_pin_ctl_cache ( struct hda_codec * codec , hda_nid_t pin ,
unsigned int val )
{
return _snd_hda_set_pin_ctl ( codec , pin , val , true ) ;
}
2013-01-10 08:38:04 +01:00
int snd_hda_codec_get_pin_target ( struct hda_codec * codec , hda_nid_t nid ) ;
int snd_hda_codec_set_pin_target ( struct hda_codec * codec , hda_nid_t nid ,
unsigned int val ) ;
2015-03-03 10:07:24 +01:00
# define for_each_hda_codec_node(nid, codec) \
for ( ( nid ) = ( codec ) - > core . start_nid ; ( nid ) < ( codec ) - > core . end_nid ; ( nid ) + + )
2005-11-21 16:33:22 +01:00
/*
* get widget capabilities
*/
static inline u32 get_wcaps ( struct hda_codec * codec , hda_nid_t nid )
{
2015-03-03 10:07:24 +01:00
if ( nid < codec - > core . start_nid | |
nid > = codec - > core . start_nid + codec - > core . num_nodes )
2008-01-22 15:37:13 +01:00
return 0 ;
2015-03-03 10:07:24 +01:00
return codec - > wcaps [ nid - codec - > core . start_nid ] ;
2005-11-21 16:33:22 +01:00
}
2009-07-27 12:54:26 +02:00
/* get the widget type from widget capability bits */
2012-01-10 12:41:22 +01:00
static inline int get_wcaps_type ( unsigned int wcaps )
{
if ( ! wcaps )
return - 1 ; /* invalid type */
return ( wcaps & AC_WCAP_TYPE ) > > AC_WCAP_TYPE_SHIFT ;
}
2009-07-27 12:54:26 +02:00
2009-08-24 09:50:46 +08:00
static inline unsigned int get_wcaps_channels ( u32 wcaps )
{
unsigned int chans ;
chans = ( wcaps & AC_WCAP_CHAN_CNT_EXT ) > > 13 ;
chans = ( ( chans < < 1 ) | 1 ) + 1 ;
return chans ;
}
2013-06-19 07:54:09 +02:00
static inline void snd_hda_override_wcaps ( struct hda_codec * codec ,
hda_nid_t nid , u32 val )
{
2015-03-03 10:07:24 +01:00
if ( nid > = codec - > core . start_nid & &
nid < codec - > core . start_nid + codec - > core . num_nodes )
codec - > wcaps [ nid - codec - > core . start_nid ] = val ;
2013-06-19 07:54:09 +02:00
}
2008-01-24 11:49:21 +01:00
u32 query_amp_caps ( struct hda_codec * codec , hda_nid_t nid , int direction ) ;
2007-05-29 19:01:37 +02:00
int snd_hda_override_amp_caps ( struct hda_codec * codec , hda_nid_t nid , int dir ,
unsigned int caps ) ;
2015-02-26 08:54:56 +01:00
/**
* snd_hda_query_pin_caps - Query PIN capabilities
* @ codec : the HD - auio codec
* @ nid : the NID to query
*
* Query PIN capabilities for the given widget .
* Returns the obtained capability bits .
*
* When cap bits have been already read , this doesn ' t read again but
* returns the cached value .
*/
static inline u32
snd_hda_query_pin_caps ( struct hda_codec * codec , hda_nid_t nid )
{
return snd_hda_param_read ( codec , nid , AC_PAR_PIN_CAP ) ;
}
/**
* snd_hda_override_pin_caps - Override the pin capabilities
* @ codec : the CODEC
* @ nid : the NID to override
* @ caps : the capability bits to set
*
* Override the cached PIN capabilitiy bits value by the given one .
*
* Returns zero if successful or a negative error code .
*/
static inline int
snd_hda_override_pin_caps ( struct hda_codec * codec , hda_nid_t nid ,
unsigned int caps )
{
return snd_hdac_override_parm ( & codec - > core , nid , AC_PAR_PIN_CAP , caps ) ;
}
2014-09-23 10:38:17 +02:00
bool snd_hda_check_amp_caps ( struct hda_codec * codec , hda_nid_t nid ,
int dir , unsigned int bits ) ;
# define nid_has_mute(codec, nid, dir) \
snd_hda_check_amp_caps ( codec , nid , dir , ( AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE ) )
# define nid_has_volume(codec, nid, dir) \
snd_hda_check_amp_caps ( codec , nid , dir , AC_AMPCAP_NUM_STEPS )
2011-05-17 09:53:31 +02:00
ALSA: hda - introduce HDA_SUBDEV_AMP_FLAG (ControlAmp in proc)
The purpose of this changeset is to show information about amplifier
setting in the codec proc file. Something like:
Control: name="Front Playback Volume", index=0, device=0
ControlAmp: chs=3, dir=Out, idx=0, ofs=0
Control: name="Front Playback Switch", index=0, device=0
ControlAmp: chs=3, dir=In, idx=2, ofs=0
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
2009-12-08 17:45:25 +01:00
/* flags for hda_nid_item */
# define HDA_NID_ITEM_AMP (1<<0)
2009-11-11 13:43:01 +01:00
struct hda_nid_item {
struct snd_kcontrol * kctl ;
2009-12-08 16:13:32 +01:00
unsigned int index ;
2009-11-11 13:43:01 +01:00
hda_nid_t nid ;
ALSA: hda - introduce HDA_SUBDEV_AMP_FLAG (ControlAmp in proc)
The purpose of this changeset is to show information about amplifier
setting in the codec proc file. Something like:
Control: name="Front Playback Volume", index=0, device=0
ControlAmp: chs=3, dir=Out, idx=0, ofs=0
Control: name="Front Playback Switch", index=0, device=0
ControlAmp: chs=3, dir=In, idx=2, ofs=0
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
2009-12-08 17:45:25 +01:00
unsigned short flags ;
2009-11-11 13:43:01 +01:00
} ;
int snd_hda_ctl_add ( struct hda_codec * codec , hda_nid_t nid ,
struct snd_kcontrol * kctl ) ;
2009-12-08 16:13:32 +01:00
int snd_hda_add_nid ( struct hda_codec * codec , struct snd_kcontrol * kctl ,
unsigned int index , hda_nid_t nid ) ;
2008-07-30 15:01:45 +02:00
void snd_hda_ctls_clear ( struct hda_codec * codec ) ;
2007-07-27 18:58:06 +02:00
/*
* hwdep interface
*/
2008-07-30 15:01:46 +02:00
# ifdef CONFIG_SND_HDA_HWDEP
2007-07-27 18:58:06 +02:00
int snd_hda_create_hwdep ( struct hda_codec * codec ) ;
2008-07-30 15:01:46 +02:00
# else
static inline int snd_hda_create_hwdep ( struct hda_codec * codec ) { return 0 ; }
# endif
2007-07-27 18:58:06 +02:00
2014-02-25 10:38:13 +01:00
void snd_hda_sysfs_init ( struct hda_codec * codec ) ;
void snd_hda_sysfs_clear ( struct hda_codec * codec ) ;
extern const struct attribute_group * snd_hda_dev_attr_groups [ ] ;
2009-03-02 14:25:17 +01:00
# ifdef CONFIG_SND_HDA_RECONFIG
const char * snd_hda_get_hint ( struct hda_codec * codec , const char * key ) ;
int snd_hda_get_bool_hint ( struct hda_codec * codec , const char * key ) ;
2013-01-11 17:40:31 +01:00
int snd_hda_get_int_hint ( struct hda_codec * codec , const char * key , int * valp ) ;
2009-03-02 14:25:17 +01:00
# else
static inline
const char * snd_hda_get_hint ( struct hda_codec * codec , const char * key )
{
return NULL ;
}
static inline
int snd_hda_get_bool_hint ( struct hda_codec * codec , const char * key )
{
return - ENOENT ;
}
2013-01-11 17:40:31 +01:00
static inline
int snd_hda_get_int_hint ( struct hda_codec * codec , const char * key , int * valp )
{
return - ENOENT ;
}
2009-03-02 14:25:17 +01:00
# endif
2007-08-10 17:21:45 +02:00
/*
* power - management
*/
void snd_hda_schedule_power_save ( struct hda_codec * codec ) ;
struct hda_amp_list {
hda_nid_t nid ;
unsigned char dir ;
unsigned char idx ;
} ;
struct hda_loopback_check {
2011-05-02 11:29:30 +02:00
const struct hda_amp_list * amplist ;
2007-08-10 17:21:45 +02:00
int power_on ;
} ;
int snd_hda_check_amp_list_power ( struct hda_codec * codec ,
struct hda_loopback_check * check ,
hda_nid_t nid ) ;
2013-01-24 17:47:17 +01:00
/* check whether the actual power state matches with the target state */
static inline bool
snd_hda_check_power_state ( struct hda_codec * codec , hda_nid_t nid ,
unsigned int target_state )
{
unsigned int state = snd_hda_codec_read ( codec , nid , 0 ,
AC_VERB_GET_POWER_STATE , 0 ) ;
if ( state & AC_PWRST_ERROR )
return true ;
state = ( state > > 4 ) & 0x0f ;
2013-06-18 07:55:02 +02:00
return ( state = = target_state ) ;
2013-01-24 17:47:17 +01:00
}
2013-03-13 14:47:21 +01:00
unsigned int snd_hda_codec_eapd_power_filter ( struct hda_codec * codec ,
hda_nid_t nid ,
unsigned int power_state ) ;
2008-09-11 09:49:39 -04:00
/*
* AMP control callbacks
*/
/* retrieve parameters from private_value */
2009-11-11 13:43:01 +01:00
# define get_amp_nid_(pv) ((pv) & 0xffff)
# define get_amp_nid(kc) get_amp_nid_((kc)->private_value)
2008-09-11 09:49:39 -04:00
# define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
2011-10-27 16:33:27 +02:00
# define get_amp_direction_(pv) (((pv) >> 18) & 0x1)
# define get_amp_direction(kc) get_amp_direction_((kc)->private_value)
2012-12-14 16:09:29 +01:00
# define get_amp_index_(pv) (((pv) >> 19) & 0xf)
# define get_amp_index(kc) get_amp_index_((kc)->private_value)
2009-01-20 13:07:55 +01:00
# define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f)
2010-10-15 10:32:50 +02:00
# define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1)
2008-09-11 09:49:39 -04:00
2012-11-30 18:34:38 +01:00
/*
* enum control helper
*/
int snd_hda_enum_helper_info ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ,
int num_entries , const char * const * texts ) ;
# define snd_hda_enum_bool_helper_info(kcontrol, uinfo) \
snd_hda_enum_helper_info ( kcontrol , uinfo , 0 , NULL )
2008-11-18 11:47:52 +08:00
/*
* CEA Short Audio Descriptor data
*/
struct cea_sad {
int channels ;
int format ; /* (format == 0) indicates invalid SAD */
int rates ;
int sample_bits ; /* for LPCM */
int max_bitrate ; /* for AC3...ATRAC */
int profile ; /* for WMAPRO */
} ;
# define ELD_FIXED_BYTES 20
2011-09-30 16:35:41 -05:00
# define ELD_MAX_SIZE 256
2008-11-18 11:47:52 +08:00
# define ELD_MAX_MNL 16
# define ELD_MAX_SAD 16
/*
* ELD : EDID Like Data
*/
2013-02-19 16:11:24 +01:00
struct parsed_hdmi_eld {
/*
* all fields will be cleared before updating ELD
*/
2008-11-18 11:47:52 +08:00
int baseline_len ;
2009-11-18 12:38:01 +08:00
int eld_ver ;
2008-11-18 11:47:52 +08:00
int cea_edid_ver ;
char monitor_name [ ELD_MAX_MNL + 1 ] ;
int manufacture_id ;
int product_id ;
u64 port_id ;
int support_hdcp ;
int support_ai ;
int conn_type ;
int aud_synch_delay ;
int spk_alloc ;
int sad_count ;
struct cea_sad sad [ ELD_MAX_SAD ] ;
2013-02-19 16:11:24 +01:00
} ;
struct hdmi_eld {
bool monitor_present ;
bool eld_valid ;
int eld_size ;
2011-09-30 16:35:41 -05:00
char eld_buffer [ ELD_MAX_SIZE ] ;
2013-02-19 16:11:24 +01:00
struct parsed_hdmi_eld info ;
2008-11-18 11:47:52 +08:00
} ;
int snd_hdmi_get_eld_size ( struct hda_codec * codec , hda_nid_t nid ) ;
2013-02-19 16:11:24 +01:00
int snd_hdmi_get_eld ( struct hda_codec * codec , hda_nid_t nid ,
unsigned char * buf , int * eld_size ) ;
2014-06-06 18:04:34 +02:00
int snd_hdmi_parse_eld ( struct hda_codec * codec , struct parsed_hdmi_eld * e ,
2013-02-19 16:11:24 +01:00
const unsigned char * buf , int size ) ;
2014-06-06 18:04:34 +02:00
void snd_hdmi_show_eld ( struct hda_codec * codec , struct parsed_hdmi_eld * e ) ;
2013-02-19 16:11:24 +01:00
void snd_hdmi_eld_update_pcm_info ( struct parsed_hdmi_eld * e ,
2011-06-01 11:14:20 -06:00
struct hda_pcm_stream * hinfo ) ;
2008-11-18 11:47:52 +08:00
2013-10-24 21:10:36 +03:00
int snd_hdmi_get_eld_ati ( struct hda_codec * codec , hda_nid_t nid ,
unsigned char * buf , int * eld_size ,
bool rev3_or_later ) ;
2015-05-27 19:45:45 +08:00
# ifdef CONFIG_SND_PROC_FS
2013-10-17 18:21:12 +02:00
void snd_hdmi_print_eld_info ( struct hdmi_eld * eld ,
struct snd_info_buffer * buffer ) ;
void snd_hdmi_write_eld_info ( struct hdmi_eld * eld ,
struct snd_info_buffer * buffer ) ;
2008-11-18 11:47:53 +08:00
# endif
2008-11-19 08:56:16 +08:00
# define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
void snd_print_channel_allocation ( int spk_alloc , char * buf , int buflen ) ;
2014-02-25 12:21:03 +01:00
/*
*/
2015-02-17 15:25:37 +01:00
# define codec_err(codec, fmt, args...) \
dev_err ( hda_codec_dev ( codec ) , fmt , # # args )
# define codec_warn(codec, fmt, args...) \
dev_warn ( hda_codec_dev ( codec ) , fmt , # # args )
# define codec_info(codec, fmt, args...) \
dev_info ( hda_codec_dev ( codec ) , fmt , # # args )
# define codec_dbg(codec, fmt, args...) \
dev_dbg ( hda_codec_dev ( codec ) , fmt , # # args )
2014-02-25 12:21:03 +01:00
2005-04-16 15:20:36 -07:00
# endif /* __SOUND_HDA_LOCAL_H */