2005-04-16 15:20:36 -07:00
/*
* Universal Interface for Intel High Definition Audio Codec
*
2011-07-07 18:23:21 +02:00
* HD audio interface patch for Realtek ALC codecs
2005-04-16 15:20:36 -07:00
*
2005-12-05 19:42:22 +01:00
* Copyright ( c ) 2004 Kailang Yang < kailang @ realtek . com . tw >
* PeiSen Hou < pshou @ realtek . com . tw >
2005-04-16 15:20:36 -07:00
* Takashi Iwai < tiwai @ suse . de >
2012-03-27 13:01:01 +10:30
* Jonathan Woithe < jwoithe @ just42 . net >
2005-04-16 15:20:36 -07:00
*
* This driver 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 driver 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
*/
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/slab.h>
# include <linux/pci.h>
2013-01-10 17:33:58 +01:00
# include <linux/dmi.h>
2011-07-15 12:38:28 -04:00
# include <linux/module.h>
2005-04-16 15:20:36 -07:00
# include <sound/core.h>
2010-09-14 23:22:00 +02:00
# include <sound/jack.h>
2005-04-16 15:20:36 -07:00
# include "hda_codec.h"
# include "hda_local.h"
2012-05-07 17:17:32 +02:00
# include "hda_auto_parser.h"
2011-10-27 22:12:46 +02:00
# include "hda_jack.h"
2012-12-19 15:22:24 +01:00
# include "hda_generic.h"
2005-04-16 15:20:36 -07:00
2011-07-07 18:23:21 +02:00
/* unsol event tags */
2012-12-19 15:22:24 +01:00
# define ALC_DCVOL_EVENT 0x08
2010-06-23 17:51:26 +02:00
2005-12-05 19:42:22 +01:00
/* for GPIO Poll */
# define GPIO_MASK 0x03
2009-04-22 16:31:35 +02:00
/* extra amp-initialization sequence types */
enum {
ALC_INIT_NONE ,
ALC_INIT_DEFAULT ,
ALC_INIT_GPIO1 ,
ALC_INIT_GPIO2 ,
ALC_INIT_GPIO3 ,
} ;
2010-03-19 11:23:45 +01:00
struct alc_customize_define {
unsigned int sku_cfg ;
unsigned char port_connectivity ;
unsigned char check_sum ;
unsigned char customization ;
unsigned char external_amp ;
unsigned int enable_pcbeep : 1 ;
unsigned int platform_type : 1 ;
unsigned int swap : 1 ;
unsigned int override : 1 ;
2010-10-14 14:50:18 +02:00
unsigned int fixup : 1 ; /* Means that this sku is set by driver, not read from hw */
2010-03-19 11:23:45 +01:00
} ;
2005-04-16 15:20:36 -07:00
struct alc_spec {
2012-12-19 15:22:24 +01:00
struct hda_gen_spec gen ; /* must be at head */
2012-05-07 17:17:32 +02:00
2005-04-16 15:20:36 -07:00
/* codec parameterization */
2011-05-02 11:30:18 +02:00
const struct snd_kcontrol_new * mixers [ 5 ] ; /* mixer arrays */
2005-04-16 15:20:36 -07:00
unsigned int num_mixers ;
2009-02-06 16:11:25 +01:00
unsigned int beep_amp ; /* beep amp value, set via set_beep_amp() */
2005-04-16 15:20:36 -07:00
2010-03-19 11:23:45 +01:00
struct alc_customize_define cdefine ;
2012-12-19 15:22:24 +01:00
unsigned int parse_flags ; /* flag for snd_hda_parse_pin_defcfg() */
2006-03-01 14:16:17 +01:00
2012-12-19 15:22:24 +01:00
/* inverted dmic fix */
unsigned int inv_dmic_fixup : 1 ; /* has inverted digital-mic workaround */
unsigned int inv_dmic_muted : 1 ; /* R-ch of inv d-mic is muted? */
2012-06-22 14:30:29 +02:00
hda_nid_t inv_dmic_pin ;
2006-03-01 14:16:17 +01:00
2013-01-10 17:33:58 +01:00
/* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
int mute_led_polarity ;
hda_nid_t mute_led_nid ;
2013-03-18 14:15:58 +01:00
unsigned int gpio_led ; /* used for alc269_fixup_hp_gpio_led() */
2006-03-03 16:47:17 +01:00
/* hooks */
void ( * init_hook ) ( struct hda_codec * codec ) ;
2012-08-24 18:38:08 +02:00
# ifdef CONFIG_PM
2009-12-27 18:52:08 -05:00
void ( * power_hook ) ( struct hda_codec * codec ) ;
2009-12-20 22:51:31 +01:00
# endif
2011-04-07 10:37:16 +02:00
void ( * shutup ) ( struct hda_codec * codec ) ;
2011-04-28 12:18:53 +02:00
2009-04-22 16:31:35 +02:00
int init_amp ;
2010-09-20 15:11:54 +02:00
int codec_variant ; /* flag for other variants */
2009-01-20 18:32:55 +01:00
2008-06-04 12:39:38 +02:00
/* for PLL fix */
hda_nid_t pll_nid ;
unsigned int pll_coef_idx , pll_coef_bit ;
2011-10-17 16:50:59 +02:00
unsigned int coef0 ;
2005-12-05 19:42:22 +01:00
} ;
2008-10-31 15:01:37 +01:00
/*
2011-07-07 18:23:21 +02:00
* Append the given mixer and verb elements for the later use
* The mixer array is referred in build_controls ( ) , and init_verbs are
* called in init ( ) .
2008-10-31 15:01:37 +01:00
*/
2011-05-02 11:30:18 +02:00
static void add_mixer ( struct alc_spec * spec , const struct snd_kcontrol_new * mix )
2008-10-31 15:01:37 +01:00
{
if ( snd_BUG_ON ( spec - > num_mixers > = ARRAY_SIZE ( spec - > mixers ) ) )
return ;
spec - > mixers [ spec - > num_mixers + + ] = mix ;
}
2005-12-05 19:42:22 +01:00
/*
2011-07-07 18:23:21 +02:00
* GPIO setup tables , used in initialization
2005-12-05 19:42:22 +01:00
*/
2007-04-12 13:06:07 +02:00
/* Enable GPIO mask and set output */
2011-05-02 11:30:18 +02:00
static const struct hda_verb alc_gpio1_init_verbs [ ] = {
2007-04-12 13:06:07 +02:00
{ 0x01 , AC_VERB_SET_GPIO_MASK , 0x01 } ,
{ 0x01 , AC_VERB_SET_GPIO_DIRECTION , 0x01 } ,
{ 0x01 , AC_VERB_SET_GPIO_DATA , 0x01 } ,
{ }
} ;
2011-05-02 11:30:18 +02:00
static const struct hda_verb alc_gpio2_init_verbs [ ] = {
2007-04-12 13:06:07 +02:00
{ 0x01 , AC_VERB_SET_GPIO_MASK , 0x02 } ,
{ 0x01 , AC_VERB_SET_GPIO_DIRECTION , 0x02 } ,
{ 0x01 , AC_VERB_SET_GPIO_DATA , 0x02 } ,
{ }
} ;
2011-05-02 11:30:18 +02:00
static const struct hda_verb alc_gpio3_init_verbs [ ] = {
2007-05-08 15:19:08 +02:00
{ 0x01 , AC_VERB_SET_GPIO_MASK , 0x03 } ,
{ 0x01 , AC_VERB_SET_GPIO_DIRECTION , 0x03 } ,
{ 0x01 , AC_VERB_SET_GPIO_DATA , 0x03 } ,
{ }
} ;
2008-06-04 12:39:38 +02:00
/*
* Fix hardware PLL issue
* On some codecs , the analog PLL gating control must be off while
* the default value is 1.
*/
static void alc_fix_pll ( struct hda_codec * codec )
{
struct alc_spec * spec = codec - > spec ;
unsigned int val ;
if ( ! spec - > pll_nid )
return ;
snd_hda_codec_write ( codec , spec - > pll_nid , 0 , AC_VERB_SET_COEF_INDEX ,
spec - > pll_coef_idx ) ;
val = snd_hda_codec_read ( codec , spec - > pll_nid , 0 ,
AC_VERB_GET_PROC_COEF , 0 ) ;
snd_hda_codec_write ( codec , spec - > pll_nid , 0 , AC_VERB_SET_COEF_INDEX ,
spec - > pll_coef_idx ) ;
snd_hda_codec_write ( codec , spec - > pll_nid , 0 , AC_VERB_SET_PROC_COEF ,
val & ~ ( 1 < < spec - > pll_coef_bit ) ) ;
}
static void alc_fix_pll_init ( struct hda_codec * codec , hda_nid_t nid ,
unsigned int coef_idx , unsigned int coef_bit )
{
struct alc_spec * spec = codec - > spec ;
spec - > pll_nid = nid ;
spec - > pll_coef_idx = coef_idx ;
spec - > pll_coef_bit = coef_bit ;
alc_fix_pll ( codec ) ;
}
2012-02-20 16:31:07 +01:00
/* update the master volume per volume-knob's unsol event */
2012-09-25 11:31:00 +02:00
static void alc_update_knob_master ( struct hda_codec * codec , struct hda_jack_tbl * jack )
2012-02-20 16:31:07 +01:00
{
unsigned int val ;
struct snd_kcontrol * kctl ;
struct snd_ctl_elem_value * uctl ;
kctl = snd_hda_find_mixer_ctl ( codec , " Master Playback Volume " ) ;
if ( ! kctl )
return ;
uctl = kzalloc ( sizeof ( * uctl ) , GFP_KERNEL ) ;
if ( ! uctl )
return ;
2012-09-25 11:31:00 +02:00
val = snd_hda_codec_read ( codec , jack - > nid , 0 ,
2012-02-20 16:31:07 +01:00
AC_VERB_GET_VOLUME_KNOB_CONTROL , 0 ) ;
val & = HDA_AMP_VOLMASK ;
uctl - > value . integer . value [ 0 ] = val ;
uctl - > value . integer . value [ 1 ] = val ;
kctl - > put ( kctl , uctl ) ;
kfree ( uctl ) ;
}
2012-09-25 11:31:00 +02:00
static void alc880_unsol_event ( struct hda_codec * codec , unsigned int res )
2012-01-19 12:10:29 +01:00
{
2012-09-25 11:31:00 +02:00
/* For some reason, the res given from ALC880 is broken.
Here we adjust it properly . */
snd_hda_jack_unsol_event ( codec , res > > 2 ) ;
2012-01-19 12:10:29 +01:00
}
2008-05-27 12:32:25 +02:00
/* additional initialization for ALC888 variants */
static void alc888_coef_init ( struct hda_codec * codec )
{
unsigned int tmp ;
snd_hda_codec_write ( codec , 0x20 , 0 , AC_VERB_SET_COEF_INDEX , 0 ) ;
tmp = snd_hda_codec_read ( codec , 0x20 , 0 , AC_VERB_GET_PROC_COEF , 0 ) ;
snd_hda_codec_write ( codec , 0x20 , 0 , AC_VERB_SET_COEF_INDEX , 7 ) ;
2009-03-05 09:40:16 +01:00
if ( ( tmp & 0xf0 ) = = 0x20 )
2008-05-27 12:32:25 +02:00
/* alc888S-VC */
snd_hda_codec_read ( codec , 0x20 , 0 ,
AC_VERB_SET_PROC_COEF , 0x830 ) ;
else
/* alc888-VB */
snd_hda_codec_read ( codec , 0x20 , 0 ,
AC_VERB_SET_PROC_COEF , 0x3030 ) ;
}
2011-07-07 18:23:21 +02:00
/* additional initialization for ALC889 variants */
2009-07-23 10:58:29 +02:00
static void alc889_coef_init ( struct hda_codec * codec )
{
unsigned int tmp ;
snd_hda_codec_write ( codec , 0x20 , 0 , AC_VERB_SET_COEF_INDEX , 7 ) ;
tmp = snd_hda_codec_read ( codec , 0x20 , 0 , AC_VERB_GET_PROC_COEF , 0 ) ;
snd_hda_codec_write ( codec , 0x20 , 0 , AC_VERB_SET_COEF_INDEX , 7 ) ;
snd_hda_codec_write ( codec , 0x20 , 0 , AC_VERB_SET_PROC_COEF , tmp | 0x2010 ) ;
}
2010-01-19 15:46:37 +01:00
/* turn on/off EAPD control (only if available) */
static void set_eapd ( struct hda_codec * codec , hda_nid_t nid , int on )
{
if ( get_wcaps_type ( get_wcaps ( codec , nid ) ) ! = AC_WID_PIN )
return ;
if ( snd_hda_query_pin_caps ( codec , nid ) & AC_PINCAP_EAPD )
snd_hda_codec_write ( codec , nid , 0 , AC_VERB_SET_EAPD_BTLENABLE ,
on ? 2 : 0 ) ;
}
2011-04-07 10:31:43 +02:00
/* turn on/off EAPD controls of the codec */
static void alc_auto_setup_eapd ( struct hda_codec * codec , bool on )
{
/* We currently only handle front, HP */
2011-06-27 15:28:57 +02:00
static hda_nid_t pins [ ] = {
0x0f , 0x10 , 0x14 , 0x15 , 0
} ;
hda_nid_t * p ;
for ( p = pins ; * p ; p + + )
set_eapd ( codec , * p , on ) ;
2011-04-07 10:31:43 +02:00
}
2011-04-07 10:37:16 +02:00
/* generic shutup callback;
* just turning off EPAD and a little pause for avoiding pop - noise
*/
static void alc_eapd_shutup ( struct hda_codec * codec )
{
alc_auto_setup_eapd ( codec , false ) ;
msleep ( 200 ) ;
}
2011-07-07 18:23:21 +02:00
/* generic EAPD initialization */
2009-04-22 16:31:35 +02:00
static void alc_auto_init_amp ( struct hda_codec * codec , int type )
2007-04-12 13:06:07 +02:00
{
2009-04-22 16:31:35 +02:00
unsigned int tmp ;
2007-04-12 13:06:07 +02:00
2011-06-27 15:28:57 +02:00
alc_auto_setup_eapd ( codec , true ) ;
2009-04-22 16:31:35 +02:00
switch ( type ) {
case ALC_INIT_GPIO1 :
2007-04-12 13:06:07 +02:00
snd_hda_sequence_write ( codec , alc_gpio1_init_verbs ) ;
break ;
2009-04-22 16:31:35 +02:00
case ALC_INIT_GPIO2 :
2007-04-12 13:06:07 +02:00
snd_hda_sequence_write ( codec , alc_gpio2_init_verbs ) ;
break ;
2009-04-22 16:31:35 +02:00
case ALC_INIT_GPIO3 :
2007-05-08 15:19:08 +02:00
snd_hda_sequence_write ( codec , alc_gpio3_init_verbs ) ;
break ;
2009-04-22 16:31:35 +02:00
case ALC_INIT_DEFAULT :
2007-10-16 14:30:01 +02:00
switch ( codec - > vendor_id ) {
case 0x10ec0260 :
snd_hda_codec_write ( codec , 0x1a , 0 ,
AC_VERB_SET_COEF_INDEX , 7 ) ;
tmp = snd_hda_codec_read ( codec , 0x1a , 0 ,
AC_VERB_GET_PROC_COEF , 0 ) ;
snd_hda_codec_write ( codec , 0x1a , 0 ,
AC_VERB_SET_COEF_INDEX , 7 ) ;
snd_hda_codec_write ( codec , 0x1a , 0 ,
AC_VERB_SET_PROC_COEF ,
tmp | 0x2010 ) ;
break ;
case 0x10ec0262 :
case 0x10ec0880 :
case 0x10ec0882 :
case 0x10ec0883 :
case 0x10ec0885 :
2009-02-06 12:46:59 +01:00
case 0x10ec0887 :
2011-03-23 22:54:32 +01:00
/*case 0x10ec0889:*/ /* this causes an SPDIF problem */
2009-07-23 10:58:29 +02:00
alc889_coef_init ( codec ) ;
2007-10-16 14:30:01 +02:00
break ;
2008-05-27 12:32:25 +02:00
case 0x10ec0888 :
2009-04-22 16:31:35 +02:00
alc888_coef_init ( codec ) ;
2008-05-27 12:32:25 +02:00
break ;
2010-01-25 15:44:11 +01:00
#if 0 /* XXX: This may cause the silent output on speaker on some machines */
2007-10-16 14:30:01 +02:00
case 0x10ec0267 :
case 0x10ec0268 :
snd_hda_codec_write ( codec , 0x20 , 0 ,
AC_VERB_SET_COEF_INDEX , 7 ) ;
tmp = snd_hda_codec_read ( codec , 0x20 , 0 ,
AC_VERB_GET_PROC_COEF , 0 ) ;
snd_hda_codec_write ( codec , 0x20 , 0 ,
2008-08-26 12:58:38 +02:00
AC_VERB_SET_COEF_INDEX , 7 ) ;
2007-10-16 14:30:01 +02:00
snd_hda_codec_write ( codec , 0x20 , 0 ,
AC_VERB_SET_PROC_COEF ,
tmp | 0x3000 ) ;
break ;
2010-01-25 15:44:11 +01:00
# endif /* XXX */
2007-04-12 13:06:07 +02:00
}
2009-04-22 16:31:35 +02:00
break ;
}
}
2012-12-19 15:22:24 +01:00
2011-07-07 18:23:21 +02:00
/*
2012-12-19 15:22:24 +01:00
* Realtek SSID verification
2011-07-07 18:23:21 +02:00
*/
2011-09-20 12:04:56 +02:00
2012-12-19 15:22:24 +01:00
/* Could be any non-zero and even value. When used as fixup, tells
* the driver to ignore any present sku defines .
*/
# define ALC_FIXUP_SKU_IGNORE (2)
2011-04-28 17:36:18 +02:00
2012-12-19 15:22:24 +01:00
static void alc_fixup_sku_ignore ( struct hda_codec * codec ,
const struct hda_fixup * fix , int action )
2011-04-28 17:36:18 +02:00
{
struct alc_spec * spec = codec - > spec ;
2012-12-19 15:22:24 +01:00
if ( action = = HDA_FIXUP_ACT_PRE_PROBE ) {
spec - > cdefine . fixup = 1 ;
spec - > cdefine . sku_cfg = ALC_FIXUP_SKU_IGNORE ;
2011-04-28 17:36:18 +02:00
}
}
2012-12-19 15:22:24 +01:00
static int alc_auto_parse_customize_define ( struct hda_codec * codec )
2009-04-22 16:31:35 +02:00
{
2012-12-19 15:22:24 +01:00
unsigned int ass , tmp , i ;
unsigned nid = 0 ;
2009-04-22 16:31:35 +02:00
struct alc_spec * spec = codec - > spec ;
2012-12-19 15:22:24 +01:00
spec - > cdefine . enable_pcbeep = 1 ; /* assume always enabled */
2009-04-22 16:31:35 +02:00
2012-12-19 15:22:24 +01:00
if ( spec - > cdefine . fixup ) {
ass = spec - > cdefine . sku_cfg ;
if ( ass = = ALC_FIXUP_SKU_IGNORE )
return - 1 ;
goto do_sku ;
2010-09-08 15:30:49 +02:00
}
2012-12-19 15:22:24 +01:00
ass = codec - > subsystem_id & 0xffff ;
if ( ass ! = codec - > bus - > pci - > subsystem_device & & ( ass & 1 ) )
goto do_sku ;
2009-04-22 16:31:35 +02:00
2012-12-19 15:22:24 +01:00
nid = 0x1d ;
if ( codec - > vendor_id = = 0x10ec0260 )
nid = 0x17 ;
ass = snd_hda_codec_get_pincfg ( codec , nid ) ;
2011-09-20 12:04:56 +02:00
2012-12-19 15:22:24 +01:00
if ( ! ( ass & 1 ) ) {
printk ( KERN_INFO " hda_codec: %s: SKU not ready 0x%08x \n " ,
codec - > chip_name , ass ) ;
return - 1 ;
2011-09-20 12:04:56 +02:00
}
2012-12-19 15:22:24 +01:00
/* check sum */
tmp = 0 ;
for ( i = 1 ; i < 16 ; i + + ) {
if ( ( ass > > i ) & 1 )
tmp + + ;
2011-04-28 18:09:52 +02:00
}
2012-12-19 15:22:24 +01:00
if ( ( ( ass > > 16 ) & 0xf ) ! = tmp )
return - 1 ;
2011-04-28 18:09:52 +02:00
2010-03-19 11:23:45 +01:00
spec - > cdefine . port_connectivity = ass > > 30 ;
spec - > cdefine . enable_pcbeep = ( ass & 0x100000 ) > > 20 ;
spec - > cdefine . check_sum = ( ass > > 16 ) & 0xf ;
spec - > cdefine . customization = ass > > 8 ;
do_sku :
spec - > cdefine . sku_cfg = ass ;
spec - > cdefine . external_amp = ( ass & 0x38 ) > > 3 ;
spec - > cdefine . platform_type = ( ass & 0x4 ) > > 2 ;
spec - > cdefine . swap = ( ass & 0x2 ) > > 1 ;
spec - > cdefine . override = ass & 0x1 ;
snd_printd ( " SKU: Nid=0x%x sku_cfg=0x%08x \n " ,
nid , spec - > cdefine . sku_cfg ) ;
snd_printd ( " SKU: port_connectivity=0x%x \n " ,
spec - > cdefine . port_connectivity ) ;
snd_printd ( " SKU: enable_pcbeep=0x%x \n " , spec - > cdefine . enable_pcbeep ) ;
snd_printd ( " SKU: check_sum=0x%08x \n " , spec - > cdefine . check_sum ) ;
snd_printd ( " SKU: customization=0x%08x \n " , spec - > cdefine . customization ) ;
snd_printd ( " SKU: external_amp=0x%x \n " , spec - > cdefine . external_amp ) ;
snd_printd ( " SKU: platform_type=0x%x \n " , spec - > cdefine . platform_type ) ;
snd_printd ( " SKU: swap=0x%x \n " , spec - > cdefine . swap ) ;
snd_printd ( " SKU: override=0x%x \n " , spec - > cdefine . override ) ;
return 0 ;
}
2012-12-19 15:22:24 +01:00
/* return the position of NID in the list, or -1 if not found */
static int find_idx_in_nid_list ( hda_nid_t nid , const hda_nid_t * list , int nums )
{
int i ;
for ( i = 0 ; i < nums ; i + + )
if ( list [ i ] = = nid )
return i ;
return - 1 ;
}
2011-07-07 18:23:21 +02:00
/* return true if the given NID is found in the list */
2011-06-27 12:34:01 +02:00
static bool found_in_nid_list ( hda_nid_t nid , const hda_nid_t * list , int nums )
{
2011-07-07 15:01:13 +02:00
return find_idx_in_nid_list ( nid , list , nums ) > = 0 ;
2011-06-27 12:34:01 +02:00
}
2009-04-22 16:31:35 +02:00
/* check subsystem ID and set up device-specific initialization;
* return 1 if initialized , 0 if invalid SSID
*/
/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
* 31 ~ 16 : Manufacture ID
* 15 ~ 8 : SKU ID
* 7 ~ 0 : Assembly ID
* port - A - - > pin 39 / 41 , port - E - - > pin 14 / 15 , port - D - - > pin 35 / 36
*/
static int alc_subsystem_id ( struct hda_codec * codec ,
hda_nid_t porta , hda_nid_t porte ,
2010-02-25 08:36:52 +01:00
hda_nid_t portd , hda_nid_t porti )
2009-04-22 16:31:35 +02:00
{
unsigned int ass , tmp , i ;
unsigned nid ;
struct alc_spec * spec = codec - > spec ;
2010-10-14 14:50:18 +02:00
if ( spec - > cdefine . fixup ) {
ass = spec - > cdefine . sku_cfg ;
if ( ass = = ALC_FIXUP_SKU_IGNORE )
return 0 ;
goto do_sku ;
}
2009-04-22 16:31:35 +02:00
ass = codec - > subsystem_id & 0xffff ;
if ( ( ass ! = codec - > bus - > pci - > subsystem_device ) & & ( ass & 1 ) )
goto do_sku ;
/* invalid SSID, check the special NID pin defcfg instead */
/*
2009-06-16 16:00:15 -04:00
* 31 ~ 30 : port connectivity
2009-04-22 16:31:35 +02:00
* 29 ~ 21 : reserve
* 20 : PCBEEP input
* 19 ~ 16 : Check sum ( 15 : 1 )
* 15 ~ 1 : Custom
* 0 : override
*/
nid = 0x1d ;
if ( codec - > vendor_id = = 0x10ec0260 )
nid = 0x17 ;
ass = snd_hda_codec_get_pincfg ( codec , nid ) ;
snd_printd ( " realtek: No valid SSID, "
" checking pincfg 0x%08x for NID 0x%x \n " ,
2009-04-28 13:03:19 +02:00
ass , nid ) ;
2010-02-25 08:36:52 +01:00
if ( ! ( ass & 1 ) )
2009-04-22 16:31:35 +02:00
return 0 ;
if ( ( ass > > 30 ) ! = 1 ) /* no physical connection */
return 0 ;
/* check sum */
tmp = 0 ;
for ( i = 1 ; i < 16 ; i + + ) {
if ( ( ass > > i ) & 1 )
tmp + + ;
}
if ( ( ( ass > > 16 ) & 0xf ) ! = tmp )
return 0 ;
do_sku :
snd_printd ( " realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x \n " ,
ass & 0xffff , codec - > vendor_id ) ;
/*
* 0 : override
* 1 : Swap Jack
* 2 : 0 - - > Desktop , 1 - - > Laptop
* 3 ~ 5 : External Amplifier control
* 7 ~ 6 : Reserved
*/
tmp = ( ass & 0x38 ) > > 3 ; /* external Amp control */
switch ( tmp ) {
case 1 :
spec - > init_amp = ALC_INIT_GPIO1 ;
break ;
case 3 :
spec - > init_amp = ALC_INIT_GPIO2 ;
break ;
case 7 :
spec - > init_amp = ALC_INIT_GPIO3 ;
break ;
case 5 :
2010-11-26 17:11:18 +01:00
default :
2009-04-22 16:31:35 +02:00
spec - > init_amp = ALC_INIT_DEFAULT ;
2007-04-12 13:06:07 +02:00
break ;
}
2008-08-26 12:58:38 +02:00
2008-01-10 13:03:59 +01:00
/* is laptop or Desktop and enable the function "Mute internal speaker
2007-10-16 14:30:01 +02:00
* when the external headphone out jack is plugged "
*/
2008-01-10 13:03:59 +01:00
if ( ! ( ass & 0x8000 ) )
2009-04-22 16:31:35 +02:00
return 1 ;
2007-10-16 14:30:01 +02:00
/*
* 10 ~ 8 : Jack location
* 12 ~ 11 : Headphone out - > 00 : PortA , 01 : PortE , 02 : PortD , 03 : Resvered
* 14 ~ 13 : Resvered
* 15 : 1 - - > enable the function " Mute internal speaker
* when the external headphone out jack is plugged "
*/
2012-12-19 15:22:24 +01:00
if ( ! spec - > gen . autocfg . hp_pins [ 0 ] & &
! ( spec - > gen . autocfg . line_out_pins [ 0 ] & &
spec - > gen . autocfg . line_out_type = = AUTO_PIN_HP_OUT ) ) {
2009-10-06 13:21:54 +02:00
hda_nid_t nid ;
2007-10-16 14:30:01 +02:00
tmp = ( ass > > 11 ) & 0x3 ; /* HP to chassis */
if ( tmp = = 0 )
2009-10-06 13:21:54 +02:00
nid = porta ;
2007-10-16 14:30:01 +02:00
else if ( tmp = = 1 )
2009-10-06 13:21:54 +02:00
nid = porte ;
2007-10-16 14:30:01 +02:00
else if ( tmp = = 2 )
2009-10-06 13:21:54 +02:00
nid = portd ;
2010-02-25 08:36:52 +01:00
else if ( tmp = = 3 )
nid = porti ;
2007-10-16 14:30:01 +02:00
else
2009-04-22 16:31:35 +02:00
return 1 ;
2012-12-19 15:22:24 +01:00
if ( found_in_nid_list ( nid , spec - > gen . autocfg . line_out_pins ,
spec - > gen . autocfg . line_outs ) )
2011-06-27 12:34:01 +02:00
return 1 ;
2012-12-19 15:22:24 +01:00
spec - > gen . autocfg . hp_pins [ 0 ] = nid ;
2007-10-16 14:30:01 +02:00
}
2009-04-22 16:31:35 +02:00
return 1 ;
}
2008-08-26 12:58:38 +02:00
2011-07-08 16:55:13 +02:00
/* Check the validity of ALC subsystem-id
* ports contains an array of 4 pin NIDs for port - A , E , D and I */
static void alc_ssid_check ( struct hda_codec * codec , const hda_nid_t * ports )
2009-04-22 16:31:35 +02:00
{
2011-07-08 16:55:13 +02:00
if ( ! alc_subsystem_id ( codec , ports [ 0 ] , ports [ 1 ] , ports [ 2 ] , ports [ 3 ] ) ) {
2009-04-22 16:31:35 +02:00
struct alc_spec * spec = codec - > spec ;
snd_printd ( " realtek: "
" Enable default setup for auto mode as fallback \n " ) ;
spec - > init_amp = ALC_INIT_DEFAULT ;
}
2011-07-07 15:01:13 +02:00
}
2011-04-28 17:36:18 +02:00
2011-07-07 18:23:21 +02:00
/*
* COEF access helper functions
*/
2009-12-03 10:07:50 +01:00
static int alc_read_coef_idx ( struct hda_codec * codec ,
unsigned int coef_idx )
{
unsigned int val ;
snd_hda_codec_write ( codec , 0x20 , 0 , AC_VERB_SET_COEF_INDEX ,
coef_idx ) ;
val = snd_hda_codec_read ( codec , 0x20 , 0 ,
AC_VERB_GET_PROC_COEF , 0 ) ;
return val ;
}
2010-09-15 10:02:29 +02:00
static void alc_write_coef_idx ( struct hda_codec * codec , unsigned int coef_idx ,
unsigned int coef_val )
{
snd_hda_codec_write ( codec , 0x20 , 0 , AC_VERB_SET_COEF_INDEX ,
coef_idx ) ;
snd_hda_codec_write ( codec , 0x20 , 0 , AC_VERB_SET_PROC_COEF ,
coef_val ) ;
}
2011-10-17 16:50:59 +02:00
/* a special bypass for COEF 0; read the cached value at the second time */
static unsigned int alc_get_coef0 ( struct hda_codec * codec )
{
struct alc_spec * spec = codec - > spec ;
if ( ! spec - > coef0 )
spec - > coef0 = alc_read_coef_idx ( codec , 0 ) ;
return spec - > coef0 ;
}
2011-07-07 18:23:21 +02:00
/*
2008-11-23 11:31:41 +08:00
*/
2008-10-31 16:37:07 +01:00
2012-12-19 15:22:24 +01:00
static hda_nid_t get_adc_nid ( struct hda_codec * codec , int adc_idx , int imux_idx )
2008-10-31 16:37:07 +01:00
{
2012-12-19 15:22:24 +01:00
struct hda_gen_spec * spec = codec - > spec ;
if ( spec - > dyn_adc_switch )
adc_idx = spec - > dyn_adc_idx [ imux_idx ] ;
return spec - > adc_nids [ adc_idx ] ;
2008-10-31 16:37:07 +01:00
}
2012-12-17 20:29:29 +01:00
static void alc_inv_dmic_sync_adc ( struct hda_codec * codec , int adc_idx )
2008-10-31 16:37:07 +01:00
{
struct alc_spec * spec = codec - > spec ;
2012-12-19 15:22:24 +01:00
struct hda_input_mux * imux = & spec - > gen . input_mux ;
2012-12-17 20:29:29 +01:00
struct nid_path * path ;
hda_nid_t nid ;
int i , dir , parm ;
unsigned int val ;
2008-10-31 16:37:07 +01:00
2012-12-17 20:29:29 +01:00
for ( i = 0 ; i < imux - > num_items ; i + + ) {
2012-12-19 15:22:24 +01:00
if ( spec - > gen . imux_pins [ i ] = = spec - > inv_dmic_pin )
2012-12-17 20:29:29 +01:00
break ;
2009-03-23 15:21:36 +01:00
}
2012-12-17 20:29:29 +01:00
if ( i > = imux - > num_items )
return ;
2009-03-23 15:21:36 +01:00
2012-12-19 15:22:24 +01:00
path = snd_hda_get_nid_path ( codec , spec - > inv_dmic_pin ,
get_adc_nid ( codec , adc_idx , i ) ) ;
2012-12-17 20:29:29 +01:00
val = path - > ctls [ NID_PATH_MUTE_CTL ] ;
if ( ! val )
return ;
nid = get_amp_nid_ ( val ) ;
dir = get_amp_direction_ ( val ) ;
parm = AC_AMP_SET_RIGHT |
( dir = = HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT ) ;
2009-03-23 15:21:36 +01:00
2012-12-20 11:33:20 +01:00
/* flush all cached amps at first */
2013-01-22 15:24:30 +01:00
snd_hda_codec_flush_cache ( codec ) ;
2009-03-23 15:21:36 +01:00
2012-12-17 20:29:29 +01:00
/* we care only right channel */
val = snd_hda_codec_amp_read ( codec , nid , 1 , dir , 0 ) ;
if ( val & 0x80 ) /* if already muted, we don't need to touch */
return ;
val | = 0x80 ;
snd_hda_codec_write ( codec , nid , 0 , AC_VERB_SET_AMP_GAIN_MUTE ,
parm | val ) ;
2008-10-31 16:37:07 +01:00
}
2012-06-22 14:30:29 +02:00
/*
* Inverted digital - mic handling
*
* First off , it ' s a bit tricky . The " Inverted Internal Mic Capture Switch "
* gives the additional mute only to the right channel of the digital mic
* capture stream . This is a workaround for avoiding the almost silence
* by summing the stereo stream from some ( known to be ForteMedia )
* digital mic unit .
*
* The logic is to call alc_inv_dmic_sync ( ) after each action ( possibly )
* modifying ADC amp . When the mute flag is set , it mutes the R - channel
* without caching so that the cache can still keep the original value .
* The cached value is then restored when the flag is set off or any other
* than d - mic is used as the current input source .
*/
static void alc_inv_dmic_sync ( struct hda_codec * codec , bool force )
{
struct alc_spec * spec = codec - > spec ;
2012-12-17 20:29:29 +01:00
int src , nums ;
2012-06-22 14:30:29 +02:00
if ( ! spec - > inv_dmic_fixup )
return ;
if ( ! spec - > inv_dmic_muted & & ! force )
return ;
2012-12-19 15:22:24 +01:00
nums = spec - > gen . dyn_adc_switch ? 1 : spec - > gen . num_adc_nids ;
2012-12-17 20:29:29 +01:00
for ( src = 0 ; src < nums ; src + + ) {
2012-06-22 14:30:29 +02:00
bool dmic_fixup = false ;
if ( spec - > inv_dmic_muted & &
2012-12-19 15:22:24 +01:00
spec - > gen . imux_pins [ spec - > gen . cur_mux [ src ] ] = = spec - > inv_dmic_pin )
2012-06-22 14:30:29 +02:00
dmic_fixup = true ;
if ( ! dmic_fixup & & ! force )
continue ;
2012-12-17 20:29:29 +01:00
alc_inv_dmic_sync_adc ( codec , src ) ;
2012-06-22 14:30:29 +02:00
}
}
2013-01-18 14:10:00 +01:00
static void alc_inv_dmic_hook ( struct hda_codec * codec ,
struct snd_ctl_elem_value * ucontrol )
2012-12-19 15:22:24 +01:00
{
alc_inv_dmic_sync ( codec , false ) ;
}
2012-06-22 14:30:29 +02:00
static int alc_inv_dmic_sw_get ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct hda_codec * codec = snd_kcontrol_chip ( kcontrol ) ;
struct alc_spec * spec = codec - > spec ;
ucontrol - > value . integer . value [ 0 ] = ! spec - > inv_dmic_muted ;
return 0 ;
}
static int alc_inv_dmic_sw_put ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct hda_codec * codec = snd_kcontrol_chip ( kcontrol ) ;
struct alc_spec * spec = codec - > spec ;
unsigned int val = ! ucontrol - > value . integer . value [ 0 ] ;
if ( val = = spec - > inv_dmic_muted )
return 0 ;
spec - > inv_dmic_muted = val ;
alc_inv_dmic_sync ( codec , true ) ;
return 0 ;
}
static const struct snd_kcontrol_new alc_inv_dmic_sw = {
. iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
2012-12-18 15:35:11 +01:00
. name = " Inverted Internal Mic Capture Switch " ,
2012-06-22 14:30:29 +02:00
. info = snd_ctl_boolean_mono_info ,
. get = alc_inv_dmic_sw_get ,
. put = alc_inv_dmic_sw_put ,
} ;
static int alc_add_inv_dmic_mixer ( struct hda_codec * codec , hda_nid_t nid )
{
struct alc_spec * spec = codec - > spec ;
2012-11-29 14:10:17 +01:00
2012-12-19 15:22:24 +01:00
if ( ! snd_hda_gen_add_kctl ( & spec - > gen , NULL , & alc_inv_dmic_sw ) )
2012-06-22 14:30:29 +02:00
return - ENOMEM ;
spec - > inv_dmic_fixup = 1 ;
spec - > inv_dmic_muted = 0 ;
spec - > inv_dmic_pin = nid ;
2012-12-19 15:22:24 +01:00
spec - > gen . cap_sync_hook = alc_inv_dmic_hook ;
2012-06-22 14:30:29 +02:00
return 0 ;
}
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
/* typically the digital mic is put at node 0x12 */
static void alc_fixup_inv_dmic_0x12 ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
{
2013-01-10 09:52:52 +01:00
if ( action = = HDA_FIXUP_ACT_PROBE )
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
alc_add_inv_dmic_mixer ( codec , 0x12 ) ;
}
2005-06-13 14:16:38 +02:00
2011-07-07 18:23:21 +02:00
# ifdef CONFIG_SND_HDA_INPUT_BEEP
/* additional beep mixers; the actual parameters are overwritten at build */
static const struct snd_kcontrol_new alc_beep_mixer [ ] = {
HDA_CODEC_VOLUME ( " Beep Playback Volume " , 0 , 0 , HDA_INPUT ) ,
HDA_CODEC_MUTE_BEEP ( " Beep Playback Switch " , 0 , 0 , HDA_INPUT ) ,
2005-06-10 19:58:24 +02:00
{ } /* end */
} ;
2011-07-07 18:23:21 +02:00
# endif
2005-06-10 19:58:24 +02:00
2012-12-19 15:22:24 +01:00
static int alc_build_controls ( struct hda_codec * codec )
2011-07-07 18:23:21 +02:00
{
struct alc_spec * spec = codec - > spec ;
2012-12-19 15:22:24 +01:00
int i , err ;
2011-04-28 15:46:07 +02:00
2012-12-19 15:22:24 +01:00
err = snd_hda_gen_build_controls ( codec ) ;
if ( err < 0 )
return err ;
2005-04-16 15:20:36 -07:00
for ( i = 0 ; i < spec - > num_mixers ; i + + ) {
err = snd_hda_add_new_ctls ( codec , spec - > mixers [ i ] ) ;
if ( err < 0 )
return err ;
}
2008-01-10 16:53:55 +01:00
2009-11-16 15:35:59 +01:00
# ifdef CONFIG_SND_HDA_INPUT_BEEP
2009-02-06 16:11:25 +01:00
/* create beep controls if needed */
if ( spec - > beep_amp ) {
2011-05-02 11:30:18 +02:00
const struct snd_kcontrol_new * knew ;
2009-02-06 16:11:25 +01:00
for ( knew = alc_beep_mixer ; knew - > name ; knew + + ) {
struct snd_kcontrol * kctl ;
kctl = snd_ctl_new1 ( knew , codec ) ;
if ( ! kctl )
2012-12-19 15:22:24 +01:00
return - ENOMEM ;
kctl - > private_value = spec - > beep_amp ;
err = snd_hda_ctl_add ( codec , 0 , kctl ) ;
if ( err < 0 )
return err ;
2011-07-07 18:23:21 +02:00
}
2008-10-21 17:01:47 +02:00
}
2012-12-19 15:22:24 +01:00
# endif
2012-02-16 16:45:59 +01:00
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_BUILD ) ;
2012-02-16 16:45:59 +01:00
return 0 ;
2007-06-05 12:30:55 +02:00
}
2005-12-05 19:42:22 +01:00
/*
2012-12-19 15:22:24 +01:00
* Common callbacks
2005-12-05 19:42:22 +01:00
*/
2007-06-05 12:30:55 +02:00
2012-12-19 15:22:24 +01:00
static int alc_init ( struct hda_codec * codec )
2011-07-07 18:23:21 +02:00
{
struct alc_spec * spec = codec - > spec ;
2007-06-05 12:30:55 +02:00
2012-12-19 15:22:24 +01:00
if ( spec - > init_hook )
spec - > init_hook ( codec ) ;
2007-06-05 12:30:55 +02:00
2012-12-19 15:22:24 +01:00
alc_fix_pll ( codec ) ;
alc_auto_init_amp ( codec , spec - > init_amp ) ;
2009-08-19 20:05:02 +02:00
2012-12-19 15:22:24 +01:00
snd_hda_gen_init ( codec ) ;
2007-06-05 12:30:55 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_INIT ) ;
2007-06-05 12:30:55 +02:00
2011-07-07 18:23:21 +02:00
return 0 ;
}
2007-06-05 12:30:55 +02:00
2012-12-19 15:22:24 +01:00
static inline void alc_shutup ( struct hda_codec * codec )
2011-07-07 18:23:21 +02:00
{
struct alc_spec * spec = codec - > spec ;
2007-06-05 12:30:55 +02:00
2012-12-19 15:22:24 +01:00
if ( spec & & spec - > shutup )
spec - > shutup ( codec ) ;
snd_hda_shutup_pins ( codec ) ;
2011-07-07 18:23:21 +02:00
}
2013-03-18 11:25:51 +01:00
# define alc_free snd_hda_gen_free
2008-01-10 16:53:55 +01:00
2012-12-19 15:22:24 +01:00
# ifdef CONFIG_PM
static void alc_power_eapd ( struct hda_codec * codec )
2011-07-07 18:23:21 +02:00
{
2012-12-19 15:22:24 +01:00
alc_auto_setup_eapd ( codec , false ) ;
2011-07-07 18:23:21 +02:00
}
2008-01-10 16:53:55 +01:00
2012-12-19 15:22:24 +01:00
static int alc_suspend ( struct hda_codec * codec )
2011-07-07 18:23:21 +02:00
{
struct alc_spec * spec = codec - > spec ;
2012-12-19 15:22:24 +01:00
alc_shutup ( codec ) ;
if ( spec & & spec - > power_hook )
spec - > power_hook ( codec ) ;
2007-06-05 12:30:55 +02:00
return 0 ;
}
2012-12-19 15:22:24 +01:00
# endif
2007-06-05 12:30:55 +02:00
2012-12-19 15:22:24 +01:00
# ifdef CONFIG_PM
static int alc_resume ( struct hda_codec * codec )
2011-07-07 18:23:21 +02:00
{
2012-12-19 15:22:24 +01:00
msleep ( 150 ) ; /* to avoid pop noise */
codec - > patch_ops . init ( codec ) ;
snd_hda_codec_resume_amp ( codec ) ;
snd_hda_codec_resume_cache ( codec ) ;
alc_inv_dmic_sync ( codec , true ) ;
hda_call_check_power_status ( codec , 0x01 ) ;
return 0 ;
2011-07-07 18:23:21 +02:00
}
2012-12-19 15:22:24 +01:00
# endif
2007-12-13 16:52:54 +01:00
2011-07-07 18:23:21 +02:00
/*
*/
2012-12-19 15:22:24 +01:00
static const struct hda_codec_ops alc_patch_ops = {
. build_controls = alc_build_controls ,
. build_pcms = snd_hda_gen_build_pcms ,
. init = alc_init ,
. free = alc_free ,
. unsol_event = snd_hda_jack_unsol_event ,
# ifdef CONFIG_PM
. resume = alc_resume ,
. suspend = alc_suspend ,
2013-01-07 12:42:48 +01:00
. check_power_status = snd_hda_gen_check_power_status ,
2012-12-19 15:22:24 +01:00
# endif
. reboot_notify = alc_shutup ,
} ;
2007-12-13 16:52:54 +01:00
2008-07-18 12:36:43 +02:00
2012-12-19 15:22:24 +01:00
/* replace the codec chip_name with the given string */
static int alc_codec_rename ( struct hda_codec * codec , const char * name )
2011-07-07 18:23:21 +02:00
{
2012-12-19 15:22:24 +01:00
kfree ( codec - > chip_name ) ;
codec - > chip_name = kstrdup ( name , GFP_KERNEL ) ;
if ( ! codec - > chip_name ) {
alc_free ( codec ) ;
return - ENOMEM ;
2011-07-07 18:23:21 +02:00
}
2007-06-05 12:30:55 +02:00
return 0 ;
2011-07-07 18:23:21 +02:00
}
2008-08-21 16:25:07 +02:00
2011-07-08 11:11:35 +02:00
/*
2012-12-19 15:22:24 +01:00
* Rename codecs appropriately from COEF value
2011-07-08 11:11:35 +02:00
*/
2012-12-19 15:22:24 +01:00
struct alc_codec_rename_table {
unsigned int vendor_id ;
unsigned short coef_mask ;
unsigned short coef_bits ;
const char * name ;
} ;
2010-02-04 14:16:14 +01:00
2012-12-19 15:22:24 +01:00
static struct alc_codec_rename_table rename_tbl [ ] = {
{ 0x10ec0269 , 0xfff0 , 0x3010 , " ALC277 " } ,
{ 0x10ec0269 , 0xf0f0 , 0x2010 , " ALC259 " } ,
{ 0x10ec0269 , 0xf0f0 , 0x3010 , " ALC258 " } ,
{ 0x10ec0269 , 0x00f0 , 0x0010 , " ALC269VB " } ,
{ 0x10ec0269 , 0xffff , 0xa023 , " ALC259 " } ,
{ 0x10ec0269 , 0xffff , 0x6023 , " ALC281X " } ,
{ 0x10ec0269 , 0x00f0 , 0x0020 , " ALC269VC " } ,
{ 0x10ec0269 , 0x00f0 , 0x0030 , " ALC269VD " } ,
{ 0x10ec0887 , 0x00f0 , 0x0030 , " ALC887-VD " } ,
{ 0x10ec0888 , 0x00f0 , 0x0030 , " ALC888-VD " } ,
{ 0x10ec0888 , 0xf0f0 , 0x3020 , " ALC886 " } ,
{ 0x10ec0899 , 0x2000 , 0x2000 , " ALC899 " } ,
{ 0x10ec0892 , 0xffff , 0x8020 , " ALC661 " } ,
{ 0x10ec0892 , 0xffff , 0x8011 , " ALC661 " } ,
{ 0x10ec0892 , 0xffff , 0x4011 , " ALC656 " } ,
{ } /* terminator */
} ;
2010-02-04 14:16:14 +01:00
2012-12-19 15:22:24 +01:00
static int alc_codec_rename_from_preset ( struct hda_codec * codec )
2011-07-07 18:23:21 +02:00
{
2012-12-19 15:22:24 +01:00
const struct alc_codec_rename_table * p ;
2008-08-26 13:13:00 +02:00
2012-12-19 15:22:24 +01:00
for ( p = rename_tbl ; p - > vendor_id ; p + + ) {
if ( p - > vendor_id ! = codec - > vendor_id )
continue ;
if ( ( alc_get_coef0 ( codec ) & p - > coef_mask ) = = p - > coef_bits )
return alc_codec_rename ( codec , p - > name ) ;
2011-07-07 18:23:21 +02:00
}
2012-12-19 15:22:24 +01:00
return 0 ;
2011-07-07 18:23:21 +02:00
}
2008-07-18 12:36:43 +02:00
2011-07-08 11:11:35 +02:00
2011-07-07 18:23:21 +02:00
/*
* Digital - beep handlers
*/
# ifdef CONFIG_SND_HDA_INPUT_BEEP
# define set_beep_amp(spec, nid, idx, dir) \
( ( spec ) - > beep_amp = HDA_COMPOSE_AMP_VAL ( nid , 3 , idx , dir ) )
2010-02-04 14:16:14 +01:00
2011-07-07 18:23:21 +02:00
static const struct snd_pci_quirk beep_white_list [ ] = {
2012-10-10 14:19:50 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x103c , " ASUS " , 1 ) ,
2011-07-07 18:23:21 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x829f , " ASUS " , 1 ) ,
2013-02-25 09:54:43 +01:00
SND_PCI_QUIRK ( 0x1043 , 0x8376 , " EeePC " , 1 ) ,
2011-07-07 18:23:21 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x83ce , " EeePC " , 1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x831a , " EeePC " , 1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x834a , " EeePC " , 1 ) ,
2012-03-06 14:02:32 +01:00
SND_PCI_QUIRK ( 0x1458 , 0xa002 , " GA-MA790X " , 1 ) ,
2011-07-07 18:23:21 +02:00
SND_PCI_QUIRK ( 0x8086 , 0xd613 , " Intel " , 1 ) ,
{ }
2010-08-06 10:02:57 +02:00
} ;
2011-07-07 18:23:21 +02:00
static inline int has_cdefine_beep ( struct hda_codec * codec )
{
struct alc_spec * spec = codec - > spec ;
const struct snd_pci_quirk * q ;
q = snd_pci_quirk_lookup ( codec - > bus - > pci , beep_white_list ) ;
if ( q )
return q - > value ;
return spec - > cdefine . enable_pcbeep ;
}
# else
# define set_beep_amp(spec, nid, idx, dir) /* NOP */
# define has_cdefine_beep(codec) 0
# endif
2010-02-04 14:16:14 +01:00
2011-07-07 18:23:21 +02:00
/* parse the BIOS configuration and set up the alc_spec */
/* return 1 if successful, 0 if the proper config is not found,
* or a negative error code
*/
2011-07-08 16:55:13 +02:00
static int alc_parse_auto_config ( struct hda_codec * codec ,
const hda_nid_t * ignore_nids ,
const hda_nid_t * ssid_nids )
2011-07-07 18:23:21 +02:00
{
struct alc_spec * spec = codec - > spec ;
2012-12-19 15:22:24 +01:00
struct auto_pin_cfg * cfg = & spec - > gen . autocfg ;
2011-07-07 18:23:21 +02:00
int err ;
2008-11-03 17:39:46 +01:00
2011-08-23 18:27:14 +02:00
err = snd_hda_parse_pin_defcfg ( codec , cfg , ignore_nids ,
spec - > parse_flags ) ;
2011-07-07 18:23:21 +02:00
if ( err < 0 )
return err ;
2011-07-08 16:55:13 +02:00
if ( ssid_nids )
alc_ssid_check ( codec , ssid_nids ) ;
2008-11-06 15:08:49 +00:00
2012-12-19 15:22:24 +01:00
err = snd_hda_gen_parse_auto_config ( codec , cfg ) ;
if ( err < 0 )
return err ;
2012-02-21 12:54:17 +01:00
2011-07-07 18:23:21 +02:00
return 1 ;
2008-08-26 13:13:00 +02:00
}
2007-12-13 16:52:54 +01:00
2012-05-07 18:03:15 +02:00
/* common preparation job for alc_spec */
static int alc_alloc_spec ( struct hda_codec * codec , hda_nid_t mixer_nid )
{
struct alc_spec * spec = kzalloc ( sizeof ( * spec ) , GFP_KERNEL ) ;
int err ;
if ( ! spec )
return - ENOMEM ;
codec - > spec = spec ;
2012-12-19 15:22:24 +01:00
snd_hda_gen_spec_init ( & spec - > gen ) ;
spec - > gen . mixer_nid = mixer_nid ;
spec - > gen . own_eapd_ctl = 1 ;
2012-12-17 20:03:15 +01:00
codec - > single_adc_amp = 1 ;
2012-12-19 15:22:24 +01:00
/* FIXME: do we need this for all Realtek codec models? */
codec - > spdif_status_reset = 1 ;
2012-05-07 18:03:15 +02:00
err = alc_codec_rename_from_preset ( codec ) ;
if ( err < 0 ) {
kfree ( spec ) ;
return err ;
}
return 0 ;
}
2011-07-08 16:55:13 +02:00
static int alc880_parse_auto_config ( struct hda_codec * codec )
{
static const hda_nid_t alc880_ignore [ ] = { 0x1d , 0 } ;
2012-04-12 22:11:25 +02:00
static const hda_nid_t alc880_ssids [ ] = { 0x15 , 0x1b , 0x14 , 0 } ;
2011-07-08 16:55:13 +02:00
return alc_parse_auto_config ( codec , alc880_ignore , alc880_ssids ) ;
}
2011-11-15 14:26:54 +01:00
/*
* ALC880 fix - ups
*/
enum {
2012-02-20 17:48:19 +01:00
ALC880_FIXUP_GPIO1 ,
2011-11-15 14:26:54 +01:00
ALC880_FIXUP_GPIO2 ,
ALC880_FIXUP_MEDION_RIM ,
2012-02-17 16:18:59 +01:00
ALC880_FIXUP_LG ,
2012-02-17 16:33:56 +01:00
ALC880_FIXUP_W810 ,
2012-02-17 17:49:54 +01:00
ALC880_FIXUP_EAPD_COEF ,
2012-02-17 17:54:44 +01:00
ALC880_FIXUP_TCL_S700 ,
2012-02-20 16:31:07 +01:00
ALC880_FIXUP_VOL_KNOB ,
ALC880_FIXUP_FUJITSU ,
2012-02-20 16:36:52 +01:00
ALC880_FIXUP_F1734 ,
2012-02-20 17:20:48 +01:00
ALC880_FIXUP_UNIWILL ,
2012-02-20 17:31:02 +01:00
ALC880_FIXUP_UNIWILL_DIG ,
2012-02-20 17:41:51 +01:00
ALC880_FIXUP_Z71V ,
2012-02-20 18:20:42 +01:00
ALC880_FIXUP_3ST_BASE ,
ALC880_FIXUP_3ST ,
ALC880_FIXUP_3ST_DIG ,
ALC880_FIXUP_5ST_BASE ,
ALC880_FIXUP_5ST ,
ALC880_FIXUP_5ST_DIG ,
ALC880_FIXUP_6ST_BASE ,
ALC880_FIXUP_6ST ,
ALC880_FIXUP_6ST_DIG ,
2013-01-23 18:21:37 +01:00
ALC880_FIXUP_6ST_AUTOMUTE ,
2011-11-15 14:26:54 +01:00
} ;
2012-02-20 16:31:07 +01:00
/* enable the volume-knob widget support on NID 0x21 */
static void alc880_fixup_vol_knob ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-02-20 16:31:07 +01:00
{
2013-01-10 09:52:52 +01:00
if ( action = = HDA_FIXUP_ACT_PROBE )
2012-09-25 11:31:00 +02:00
snd_hda_jack_detect_enable_callback ( codec , 0x21 , ALC_DCVOL_EVENT , alc_update_knob_master ) ;
2012-02-20 16:31:07 +01:00
}
2013-01-10 09:52:52 +01:00
static const struct hda_fixup alc880_fixups [ ] = {
2012-02-20 17:48:19 +01:00
[ ALC880_FIXUP_GPIO1 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2012-02-20 17:48:19 +01:00
. v . verbs = alc_gpio1_init_verbs ,
} ,
2011-11-15 14:26:54 +01:00
[ ALC880_FIXUP_GPIO2 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-15 14:26:54 +01:00
. v . verbs = alc_gpio2_init_verbs ,
} ,
[ ALC880_FIXUP_MEDION_RIM ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-15 14:26:54 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3060 } ,
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_GPIO2 ,
} ,
2012-02-17 16:18:59 +01:00
[ ALC880_FIXUP_LG ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-17 16:18:59 +01:00
/* disable bogus unused pins */
{ 0x16 , 0x411111f0 } ,
{ 0x18 , 0x411111f0 } ,
{ 0x1a , 0x411111f0 } ,
{ }
}
} ,
2012-02-17 16:33:56 +01:00
[ ALC880_FIXUP_W810 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-17 16:33:56 +01:00
/* disable bogus unused pins */
{ 0x17 , 0x411111f0 } ,
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_GPIO2 ,
} ,
2012-02-17 17:49:54 +01:00
[ ALC880_FIXUP_EAPD_COEF ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2012-02-17 17:49:54 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
/* change to EAPD mode */
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3060 } ,
{ }
} ,
} ,
2012-02-17 17:54:44 +01:00
[ ALC880_FIXUP_TCL_S700 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2012-02-17 17:54:44 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
/* change to EAPD mode */
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3070 } ,
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_GPIO2 ,
} ,
2012-02-20 16:31:07 +01:00
[ ALC880_FIXUP_VOL_KNOB ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-02-20 16:31:07 +01:00
. v . func = alc880_fixup_vol_knob ,
} ,
[ ALC880_FIXUP_FUJITSU ] = {
/* override all pins as BIOS on old Amilo is broken */
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 16:31:07 +01:00
{ 0x14 , 0x0121411f } , /* HP */
{ 0x15 , 0x99030120 } , /* speaker */
{ 0x16 , 0x99030130 } , /* bass speaker */
{ 0x17 , 0x411111f0 } , /* N/A */
{ 0x18 , 0x411111f0 } , /* N/A */
{ 0x19 , 0x01a19950 } , /* mic-in */
{ 0x1a , 0x411111f0 } , /* N/A */
{ 0x1b , 0x411111f0 } , /* N/A */
{ 0x1c , 0x411111f0 } , /* N/A */
{ 0x1d , 0x411111f0 } , /* N/A */
{ 0x1e , 0x01454140 } , /* SPDIF out */
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_VOL_KNOB ,
} ,
2012-02-20 16:36:52 +01:00
[ ALC880_FIXUP_F1734 ] = {
/* almost compatible with FUJITSU, but no bass and SPDIF */
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 16:36:52 +01:00
{ 0x14 , 0x0121411f } , /* HP */
{ 0x15 , 0x99030120 } , /* speaker */
{ 0x16 , 0x411111f0 } , /* N/A */
{ 0x17 , 0x411111f0 } , /* N/A */
{ 0x18 , 0x411111f0 } , /* N/A */
{ 0x19 , 0x01a19950 } , /* mic-in */
{ 0x1a , 0x411111f0 } , /* N/A */
{ 0x1b , 0x411111f0 } , /* N/A */
{ 0x1c , 0x411111f0 } , /* N/A */
{ 0x1d , 0x411111f0 } , /* N/A */
{ 0x1e , 0x411111f0 } , /* N/A */
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_VOL_KNOB ,
} ,
2012-02-20 17:20:48 +01:00
[ ALC880_FIXUP_UNIWILL ] = {
/* need to fix HP and speaker pins to be parsed correctly */
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 17:20:48 +01:00
{ 0x14 , 0x0121411f } , /* HP */
{ 0x15 , 0x99030120 } , /* speaker */
{ 0x16 , 0x99030130 } , /* bass speaker */
{ }
} ,
} ,
2012-02-20 17:31:02 +01:00
[ ALC880_FIXUP_UNIWILL_DIG ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 17:31:02 +01:00
/* disable bogus unused pins */
{ 0x17 , 0x411111f0 } ,
{ 0x19 , 0x411111f0 } ,
{ 0x1b , 0x411111f0 } ,
{ 0x1f , 0x411111f0 } ,
{ }
}
} ,
2012-02-20 17:41:51 +01:00
[ ALC880_FIXUP_Z71V ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 17:41:51 +01:00
/* set up the whole pins as BIOS is utterly broken */
{ 0x14 , 0x99030120 } , /* speaker */
{ 0x15 , 0x0121411f } , /* HP */
{ 0x16 , 0x411111f0 } , /* N/A */
{ 0x17 , 0x411111f0 } , /* N/A */
{ 0x18 , 0x01a19950 } , /* mic-in */
{ 0x19 , 0x411111f0 } , /* N/A */
{ 0x1a , 0x01813031 } , /* line-in */
{ 0x1b , 0x411111f0 } , /* N/A */
{ 0x1c , 0x411111f0 } , /* N/A */
{ 0x1d , 0x411111f0 } , /* N/A */
{ 0x1e , 0x0144111e } , /* SPDIF */
{ }
}
} ,
2012-02-20 18:20:42 +01:00
[ ALC880_FIXUP_3ST_BASE ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 18:20:42 +01:00
{ 0x14 , 0x01014010 } , /* line-out */
{ 0x15 , 0x411111f0 } , /* N/A */
{ 0x16 , 0x411111f0 } , /* N/A */
{ 0x17 , 0x411111f0 } , /* N/A */
{ 0x18 , 0x01a19c30 } , /* mic-in */
{ 0x19 , 0x0121411f } , /* HP */
{ 0x1a , 0x01813031 } , /* line-in */
{ 0x1b , 0x02a19c40 } , /* front-mic */
{ 0x1c , 0x411111f0 } , /* N/A */
{ 0x1d , 0x411111f0 } , /* N/A */
/* 0x1e is filled in below */
{ 0x1f , 0x411111f0 } , /* N/A */
{ }
}
} ,
[ ALC880_FIXUP_3ST ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 18:20:42 +01:00
{ 0x1e , 0x411111f0 } , /* N/A */
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_3ST_BASE ,
} ,
[ ALC880_FIXUP_3ST_DIG ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 18:20:42 +01:00
{ 0x1e , 0x0144111e } , /* SPDIF */
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_3ST_BASE ,
} ,
[ ALC880_FIXUP_5ST_BASE ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 18:20:42 +01:00
{ 0x14 , 0x01014010 } , /* front */
{ 0x15 , 0x411111f0 } , /* N/A */
{ 0x16 , 0x01011411 } , /* CLFE */
{ 0x17 , 0x01016412 } , /* surr */
{ 0x18 , 0x01a19c30 } , /* mic-in */
{ 0x19 , 0x0121411f } , /* HP */
{ 0x1a , 0x01813031 } , /* line-in */
{ 0x1b , 0x02a19c40 } , /* front-mic */
{ 0x1c , 0x411111f0 } , /* N/A */
{ 0x1d , 0x411111f0 } , /* N/A */
/* 0x1e is filled in below */
{ 0x1f , 0x411111f0 } , /* N/A */
{ }
}
} ,
[ ALC880_FIXUP_5ST ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 18:20:42 +01:00
{ 0x1e , 0x411111f0 } , /* N/A */
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_5ST_BASE ,
} ,
[ ALC880_FIXUP_5ST_DIG ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 18:20:42 +01:00
{ 0x1e , 0x0144111e } , /* SPDIF */
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_5ST_BASE ,
} ,
[ ALC880_FIXUP_6ST_BASE ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 18:20:42 +01:00
{ 0x14 , 0x01014010 } , /* front */
{ 0x15 , 0x01016412 } , /* surr */
{ 0x16 , 0x01011411 } , /* CLFE */
{ 0x17 , 0x01012414 } , /* side */
{ 0x18 , 0x01a19c30 } , /* mic-in */
{ 0x19 , 0x02a19c40 } , /* front-mic */
{ 0x1a , 0x01813031 } , /* line-in */
{ 0x1b , 0x0121411f } , /* HP */
{ 0x1c , 0x411111f0 } , /* N/A */
{ 0x1d , 0x411111f0 } , /* N/A */
/* 0x1e is filled in below */
{ 0x1f , 0x411111f0 } , /* N/A */
{ }
}
} ,
[ ALC880_FIXUP_6ST ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 18:20:42 +01:00
{ 0x1e , 0x411111f0 } , /* N/A */
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_6ST_BASE ,
} ,
[ ALC880_FIXUP_6ST_DIG ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-20 18:20:42 +01:00
{ 0x1e , 0x0144111e } , /* SPDIF */
{ }
} ,
. chained = true ,
. chain_id = ALC880_FIXUP_6ST_BASE ,
} ,
2013-01-23 18:21:37 +01:00
[ ALC880_FIXUP_6ST_AUTOMUTE ] = {
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
{ 0x1b , 0x0121401f } , /* HP with jack detect */
{ }
} ,
. chained_before = true ,
. chain_id = ALC880_FIXUP_6ST_BASE ,
} ,
2011-11-15 14:26:54 +01:00
} ;
static const struct snd_pci_quirk alc880_fixup_tbl [ ] = {
2012-02-17 16:33:56 +01:00
SND_PCI_QUIRK ( 0x1019 , 0x0f69 , " Coeus G610P " , ALC880_FIXUP_W810 ) ,
2012-02-20 17:41:51 +01:00
SND_PCI_QUIRK ( 0x1043 , 0x1964 , " ASUS Z71V " , ALC880_FIXUP_Z71V ) ,
2012-02-20 17:56:57 +01:00
SND_PCI_QUIRK_VENDOR ( 0x1043 , " ASUS " , ALC880_FIXUP_GPIO1 ) ,
SND_PCI_QUIRK ( 0x1558 , 0x5401 , " Clevo GPIO2 " , ALC880_FIXUP_GPIO2 ) ,
2012-02-17 17:49:54 +01:00
SND_PCI_QUIRK_VENDOR ( 0x1558 , " Clevo " , ALC880_FIXUP_EAPD_COEF ) ,
2012-02-20 17:31:02 +01:00
SND_PCI_QUIRK ( 0x1584 , 0x9050 , " Uniwill " , ALC880_FIXUP_UNIWILL_DIG ) ,
2012-02-20 16:36:52 +01:00
SND_PCI_QUIRK ( 0x1584 , 0x9054 , " Uniwill " , ALC880_FIXUP_F1734 ) ,
2012-02-20 17:20:48 +01:00
SND_PCI_QUIRK ( 0x1584 , 0x9070 , " Uniwill " , ALC880_FIXUP_UNIWILL ) ,
2012-02-20 17:11:38 +01:00
SND_PCI_QUIRK ( 0x1584 , 0x9077 , " Uniwill P53 " , ALC880_FIXUP_VOL_KNOB ) ,
2012-02-17 16:33:56 +01:00
SND_PCI_QUIRK ( 0x161f , 0x203d , " W810 " , ALC880_FIXUP_W810 ) ,
2011-11-15 14:26:54 +01:00
SND_PCI_QUIRK ( 0x161f , 0x205d , " Medion Rim 2150 " , ALC880_FIXUP_MEDION_RIM ) ,
2013-01-23 18:21:37 +01:00
SND_PCI_QUIRK ( 0x1631 , 0xe011 , " PB 13201056 " , ALC880_FIXUP_6ST_AUTOMUTE ) ,
2012-02-20 16:36:52 +01:00
SND_PCI_QUIRK ( 0x1734 , 0x107c , " FSC F1734 " , ALC880_FIXUP_F1734 ) ,
2012-02-20 16:31:07 +01:00
SND_PCI_QUIRK ( 0x1734 , 0x1094 , " FSC Amilo M1451G " , ALC880_FIXUP_FUJITSU ) ,
2012-02-20 16:36:52 +01:00
SND_PCI_QUIRK ( 0x1734 , 0x10ac , " FSC AMILO Xi 1526 " , ALC880_FIXUP_F1734 ) ,
2012-02-20 16:31:07 +01:00
SND_PCI_QUIRK ( 0x1734 , 0x10b0 , " FSC Amilo Pi1556 " , ALC880_FIXUP_FUJITSU ) ,
2012-02-17 16:18:59 +01:00
SND_PCI_QUIRK ( 0x1854 , 0x003b , " LG " , ALC880_FIXUP_LG ) ,
SND_PCI_QUIRK ( 0x1854 , 0x005f , " LG P1 Express " , ALC880_FIXUP_LG ) ,
SND_PCI_QUIRK ( 0x1854 , 0x0068 , " LG w1 " , ALC880_FIXUP_LG ) ,
2012-02-17 17:54:44 +01:00
SND_PCI_QUIRK ( 0x19db , 0x4188 , " TCL S700 " , ALC880_FIXUP_TCL_S700 ) ,
2012-02-20 18:20:42 +01:00
/* Below is the copied entries from alc880_quirks.c.
* It ' s not quite sure whether BIOS sets the correct pin - config table
* on these machines , thus they are kept to be compatible with
* the old static quirks . Once when it ' s confirmed to work without
* these overrides , it ' d be better to remove .
*/
SND_PCI_QUIRK ( 0x1019 , 0xa880 , " ECS " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x1019 , 0xa884 , " Acer APFV " , ALC880_FIXUP_6ST ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0070 , " ULI " , ALC880_FIXUP_3ST_DIG ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0077 , " ULI " , ALC880_FIXUP_6ST_DIG ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0078 , " ULI " , ALC880_FIXUP_6ST_DIG ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0087 , " ULI " , ALC880_FIXUP_6ST_DIG ) ,
SND_PCI_QUIRK ( 0x1025 , 0xe309 , " ULI " , ALC880_FIXUP_3ST_DIG ) ,
SND_PCI_QUIRK ( 0x1025 , 0xe310 , " ULI " , ALC880_FIXUP_3ST ) ,
SND_PCI_QUIRK ( 0x1039 , 0x1234 , NULL , ALC880_FIXUP_6ST_DIG ) ,
SND_PCI_QUIRK ( 0x104d , 0x81a0 , " Sony " , ALC880_FIXUP_3ST ) ,
SND_PCI_QUIRK ( 0x104d , 0x81d6 , " Sony " , ALC880_FIXUP_3ST ) ,
SND_PCI_QUIRK ( 0x107b , 0x3032 , " Gateway " , ALC880_FIXUP_5ST ) ,
SND_PCI_QUIRK ( 0x107b , 0x3033 , " Gateway " , ALC880_FIXUP_5ST ) ,
SND_PCI_QUIRK ( 0x107b , 0x4039 , " Gateway " , ALC880_FIXUP_5ST ) ,
SND_PCI_QUIRK ( 0x1297 , 0xc790 , " Shuttle ST20G5 " , ALC880_FIXUP_6ST_DIG ) ,
SND_PCI_QUIRK ( 0x1458 , 0xa102 , " Gigabyte K8 " , ALC880_FIXUP_6ST_DIG ) ,
SND_PCI_QUIRK ( 0x1462 , 0x1150 , " MSI " , ALC880_FIXUP_6ST_DIG ) ,
SND_PCI_QUIRK ( 0x1509 , 0x925d , " FIC P4M " , ALC880_FIXUP_6ST_DIG ) ,
SND_PCI_QUIRK ( 0x1565 , 0x8202 , " Biostar " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x1695 , 0x400d , " EPoX " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x1695 , 0x4012 , " EPox EP-5LDA " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x2668 , 0x8086 , NULL , ALC880_FIXUP_6ST_DIG ) , /* broken BIOS */
SND_PCI_QUIRK ( 0x8086 , 0x2668 , NULL , ALC880_FIXUP_6ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xa100 , " Intel mobo " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xd400 , " Intel mobo " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xd401 , " Intel mobo " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xd402 , " Intel mobo " , ALC880_FIXUP_3ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xe224 , " Intel mobo " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xe305 , " Intel mobo " , ALC880_FIXUP_3ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xe308 , " Intel mobo " , ALC880_FIXUP_3ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xe400 , " Intel mobo " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xe401 , " Intel mobo " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0x8086 , 0xe402 , " Intel mobo " , ALC880_FIXUP_5ST_DIG ) ,
/* default Intel */
SND_PCI_QUIRK_VENDOR ( 0x8086 , " Intel mobo " , ALC880_FIXUP_3ST ) ,
SND_PCI_QUIRK ( 0xa0a0 , 0x0560 , " AOpen i915GMm-HFS " , ALC880_FIXUP_5ST_DIG ) ,
SND_PCI_QUIRK ( 0xe803 , 0x1019 , NULL , ALC880_FIXUP_6ST_DIG ) ,
{ }
} ;
2013-01-10 09:52:52 +01:00
static const struct hda_model_fixup alc880_fixup_models [ ] = {
2012-02-20 18:20:42 +01:00
{ . id = ALC880_FIXUP_3ST , . name = " 3stack " } ,
{ . id = ALC880_FIXUP_3ST_DIG , . name = " 3stack-digout " } ,
{ . id = ALC880_FIXUP_5ST , . name = " 5stack " } ,
{ . id = ALC880_FIXUP_5ST_DIG , . name = " 5stack-digout " } ,
{ . id = ALC880_FIXUP_6ST , . name = " 6stack " } ,
{ . id = ALC880_FIXUP_6ST_DIG , . name = " 6stack-digout " } ,
2013-01-23 18:21:37 +01:00
{ . id = ALC880_FIXUP_6ST_AUTOMUTE , . name = " 6stack-automute " } ,
2011-11-15 14:26:54 +01:00
{ }
} ;
2011-07-07 18:23:21 +02:00
/*
* OK , here we have finally the patch for ALC880
*/
static int patch_alc880 ( struct hda_codec * codec )
2008-08-26 13:13:00 +02:00
{
2011-07-07 18:23:21 +02:00
struct alc_spec * spec ;
int err ;
2007-12-13 16:52:54 +01:00
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0x0b ) ;
if ( err < 0 )
return err ;
2008-11-06 15:08:49 +00:00
2012-05-07 18:03:15 +02:00
spec = codec - > spec ;
2012-12-19 15:22:24 +01:00
spec - > gen . need_dac_fix = 1 ;
2013-03-18 11:25:51 +01:00
spec - > gen . beep_nid = 0x01 ;
2008-07-18 12:36:43 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_pick_fixup ( codec , alc880_fixup_models , alc880_fixup_tbl ,
2012-02-20 18:20:42 +01:00
alc880_fixups ) ;
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PRE_PROBE ) ;
2011-11-15 14:26:54 +01:00
2012-02-20 18:20:42 +01:00
/* automatic parse from the BIOS config */
err = alc880_parse_auto_config ( codec ) ;
if ( err < 0 )
goto error ;
2010-08-06 10:02:57 +02:00
2013-03-18 11:25:51 +01:00
if ( ! spec - > gen . no_analog )
2011-07-08 16:55:13 +02:00
set_beep_amp ( spec , 0x0b , 0x05 , HDA_INPUT ) ;
2008-07-18 12:36:43 +02:00
2011-07-07 18:23:21 +02:00
codec - > patch_ops = alc_patch_ops ;
2012-09-25 11:31:00 +02:00
codec - > patch_ops . unsol_event = alc880_unsol_event ;
2008-07-18 12:36:43 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PROBE ) ;
2012-02-20 15:47:55 +01:00
2011-07-07 18:23:21 +02:00
return 0 ;
2011-10-17 16:39:09 +02:00
error :
alc_free ( codec ) ;
return err ;
2010-04-09 11:01:20 +02:00
}
2011-07-07 18:23:21 +02:00
2008-08-26 13:13:00 +02:00
/*
2011-07-07 18:23:21 +02:00
* ALC260 support
2008-08-26 13:13:00 +02:00
*/
2011-07-07 18:23:21 +02:00
static int alc260_parse_auto_config ( struct hda_codec * codec )
2007-12-13 16:52:54 +01:00
{
2011-07-07 18:23:21 +02:00
static const hda_nid_t alc260_ignore [ ] = { 0x17 , 0 } ;
2011-07-08 16:55:13 +02:00
static const hda_nid_t alc260_ssids [ ] = { 0x10 , 0x15 , 0x0f , 0 } ;
return alc_parse_auto_config ( codec , alc260_ignore , alc260_ssids ) ;
2007-12-13 16:52:54 +01:00
}
2011-07-07 18:23:21 +02:00
/*
* Pin config fixes
*/
enum {
2012-02-16 11:51:19 +01:00
ALC260_FIXUP_HP_DC5750 ,
ALC260_FIXUP_HP_PIN_0F ,
ALC260_FIXUP_COEF ,
2012-02-16 12:02:53 +01:00
ALC260_FIXUP_GPIO1 ,
2012-02-16 12:35:16 +01:00
ALC260_FIXUP_GPIO1_TOGGLE ,
ALC260_FIXUP_REPLACER ,
2012-02-16 12:42:30 +01:00
ALC260_FIXUP_HP_B1900 ,
2012-04-19 07:33:27 +02:00
ALC260_FIXUP_KN1 ,
2013-01-10 17:10:40 +01:00
ALC260_FIXUP_FSC_S7020 ,
2013-02-19 18:23:31 +01:00
ALC260_FIXUP_FSC_S7020_JWSE ,
2011-07-07 18:23:21 +02:00
} ;
2012-02-16 12:35:16 +01:00
static void alc260_gpio1_automute ( struct hda_codec * codec )
{
struct alc_spec * spec = codec - > spec ;
snd_hda_codec_write ( codec , 0x01 , 0 , AC_VERB_SET_GPIO_DATA ,
2012-12-19 15:22:24 +01:00
spec - > gen . hp_jack_present ) ;
2012-02-16 12:35:16 +01:00
}
static void alc260_fixup_gpio1_toggle ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-02-16 12:35:16 +01:00
{
struct alc_spec * spec = codec - > spec ;
2013-01-10 09:52:52 +01:00
if ( action = = HDA_FIXUP_ACT_PROBE ) {
2012-02-16 12:35:16 +01:00
/* although the machine has only one output pin, we need to
* toggle GPIO1 according to the jack state
*/
2012-12-19 15:22:24 +01:00
spec - > gen . automute_hook = alc260_gpio1_automute ;
spec - > gen . detect_hp = 1 ;
spec - > gen . automute_speaker = 1 ;
spec - > gen . autocfg . hp_pins [ 0 ] = 0x0f ; /* copy it for automute */
snd_hda_jack_detect_enable_callback ( codec , 0x0f , HDA_GEN_HP_EVENT ,
snd_hda_gen_hp_automute ) ;
2012-12-18 18:12:44 +01:00
snd_hda_add_verbs ( codec , alc_gpio1_init_verbs ) ;
2012-02-16 12:35:16 +01:00
}
}
2012-04-19 07:33:27 +02:00
static void alc260_fixup_kn1 ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-04-19 07:33:27 +02:00
{
struct alc_spec * spec = codec - > spec ;
2013-01-10 09:52:52 +01:00
static const struct hda_pintbl pincfgs [ ] = {
2012-04-19 07:33:27 +02:00
{ 0x0f , 0x02214000 } , /* HP/speaker */
{ 0x12 , 0x90a60160 } , /* int mic */
{ 0x13 , 0x02a19000 } , /* ext mic */
{ 0x18 , 0x01446000 } , /* SPDIF out */
/* disable bogus I/O pins */
{ 0x10 , 0x411111f0 } ,
{ 0x11 , 0x411111f0 } ,
{ 0x14 , 0x411111f0 } ,
{ 0x15 , 0x411111f0 } ,
{ 0x16 , 0x411111f0 } ,
{ 0x17 , 0x411111f0 } ,
{ 0x19 , 0x411111f0 } ,
{ }
} ;
switch ( action ) {
2013-01-10 09:52:52 +01:00
case HDA_FIXUP_ACT_PRE_PROBE :
snd_hda_apply_pincfgs ( codec , pincfgs ) ;
2012-04-19 07:33:27 +02:00
break ;
2013-01-10 09:52:52 +01:00
case HDA_FIXUP_ACT_PROBE :
2012-04-19 07:33:27 +02:00
spec - > init_amp = ALC_INIT_NONE ;
break ;
}
}
2013-01-10 17:10:40 +01:00
static void alc260_fixup_fsc_s7020 ( struct hda_codec * codec ,
const struct hda_fixup * fix , int action )
{
struct alc_spec * spec = codec - > spec ;
2013-02-19 18:23:31 +01:00
if ( action = = HDA_FIXUP_ACT_PROBE )
spec - > init_amp = ALC_INIT_NONE ;
}
2013-01-10 17:10:40 +01:00
2013-02-19 18:23:31 +01:00
static void alc260_fixup_fsc_s7020_jwse ( struct hda_codec * codec ,
const struct hda_fixup * fix , int action )
{
struct alc_spec * spec = codec - > spec ;
if ( action = = HDA_FIXUP_ACT_PRE_PROBE ) {
2013-03-07 18:32:59 +01:00
spec - > gen . add_jack_modes = 1 ;
2013-02-19 18:23:31 +01:00
spec - > gen . hp_mic = 1 ;
2013-02-18 17:04:20 +01:00
}
2013-01-10 17:10:40 +01:00
}
2013-01-10 09:52:52 +01:00
static const struct hda_fixup alc260_fixups [ ] = {
2012-02-16 11:51:19 +01:00
[ ALC260_FIXUP_HP_DC5750 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-07-07 18:23:21 +02:00
{ 0x11 , 0x90130110 } , /* speaker */
{ }
}
} ,
2012-02-16 11:51:19 +01:00
[ ALC260_FIXUP_HP_PIN_0F ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-02-16 11:51:19 +01:00
{ 0x0f , 0x01214000 } , /* HP */
{ }
}
} ,
[ ALC260_FIXUP_COEF ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2012-02-16 11:51:19 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3040 } ,
{ }
} ,
. chained = true ,
. chain_id = ALC260_FIXUP_HP_PIN_0F ,
} ,
2012-02-16 12:02:53 +01:00
[ ALC260_FIXUP_GPIO1 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2012-02-16 12:02:53 +01:00
. v . verbs = alc_gpio1_init_verbs ,
} ,
2012-02-16 12:35:16 +01:00
[ ALC260_FIXUP_GPIO1_TOGGLE ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-02-16 12:35:16 +01:00
. v . func = alc260_fixup_gpio1_toggle ,
. chained = true ,
. chain_id = ALC260_FIXUP_HP_PIN_0F ,
} ,
[ ALC260_FIXUP_REPLACER ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2012-02-16 12:35:16 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3050 } ,
{ }
} ,
. chained = true ,
. chain_id = ALC260_FIXUP_GPIO1_TOGGLE ,
} ,
2012-02-16 12:42:30 +01:00
[ ALC260_FIXUP_HP_B1900 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-02-16 12:42:30 +01:00
. v . func = alc260_fixup_gpio1_toggle ,
. chained = true ,
. chain_id = ALC260_FIXUP_COEF ,
2012-04-19 07:33:27 +02:00
} ,
[ ALC260_FIXUP_KN1 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-04-19 07:33:27 +02:00
. v . func = alc260_fixup_kn1 ,
} ,
2013-01-10 17:10:40 +01:00
[ ALC260_FIXUP_FSC_S7020 ] = {
. type = HDA_FIXUP_FUNC ,
. v . func = alc260_fixup_fsc_s7020 ,
} ,
2013-02-19 18:23:31 +01:00
[ ALC260_FIXUP_FSC_S7020_JWSE ] = {
. type = HDA_FIXUP_FUNC ,
. v . func = alc260_fixup_fsc_s7020_jwse ,
. chained = true ,
. chain_id = ALC260_FIXUP_FSC_S7020 ,
} ,
2011-07-07 18:23:21 +02:00
} ;
static const struct snd_pci_quirk alc260_fixup_tbl [ ] = {
2012-02-16 12:02:53 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x007b , " Acer C20x " , ALC260_FIXUP_GPIO1 ) ,
2012-02-16 11:51:19 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x007f , " Acer Aspire 9500 " , ALC260_FIXUP_COEF ) ,
2012-02-16 12:02:53 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x008f , " Acer " , ALC260_FIXUP_GPIO1 ) ,
2012-02-16 11:51:19 +01:00
SND_PCI_QUIRK ( 0x103c , 0x280a , " HP dc5750 " , ALC260_FIXUP_HP_DC5750 ) ,
2012-02-16 12:42:30 +01:00
SND_PCI_QUIRK ( 0x103c , 0x30ba , " HP Presario B1900 " , ALC260_FIXUP_HP_B1900 ) ,
2013-01-10 17:10:40 +01:00
SND_PCI_QUIRK ( 0x10cf , 0x1326 , " FSC LifeBook S7020 " , ALC260_FIXUP_FSC_S7020 ) ,
2012-02-16 12:45:03 +01:00
SND_PCI_QUIRK ( 0x1509 , 0x4540 , " Favorit 100XS " , ALC260_FIXUP_GPIO1 ) ,
2012-04-19 07:33:27 +02:00
SND_PCI_QUIRK ( 0x152d , 0x0729 , " Quanta KN1 " , ALC260_FIXUP_KN1 ) ,
2012-02-16 12:35:16 +01:00
SND_PCI_QUIRK ( 0x161f , 0x2057 , " Replacer 672V " , ALC260_FIXUP_REPLACER ) ,
2012-02-16 11:51:19 +01:00
SND_PCI_QUIRK ( 0x1631 , 0xc017 , " PB V7900 " , ALC260_FIXUP_COEF ) ,
2011-07-07 18:23:21 +02:00
{ }
} ;
2013-02-19 18:23:31 +01:00
static const struct hda_model_fixup alc260_fixup_models [ ] = {
{ . id = ALC260_FIXUP_GPIO1 , . name = " gpio1 " } ,
{ . id = ALC260_FIXUP_COEF , . name = " coef " } ,
{ . id = ALC260_FIXUP_FSC_S7020 , . name = " fujitsu " } ,
{ . id = ALC260_FIXUP_FSC_S7020_JWSE , . name = " fujitsu-jwse " } ,
{ }
} ;
2011-07-07 18:23:21 +02:00
/*
*/
static int patch_alc260 ( struct hda_codec * codec )
2010-09-15 10:02:29 +02:00
{
2011-07-07 18:23:21 +02:00
struct alc_spec * spec ;
2012-02-16 12:59:55 +01:00
int err ;
2011-07-07 18:23:21 +02:00
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0x07 ) ;
if ( err < 0 )
return err ;
2011-07-07 18:23:21 +02:00
2012-05-07 18:03:15 +02:00
spec = codec - > spec ;
2013-01-15 18:45:53 +01:00
/* as quite a few machines require HP amp for speaker outputs,
* it ' s easier to enable it unconditionally ; even if it ' s unneeded ,
* it ' s almost harmless .
*/
spec - > gen . prefer_hp_amp = 1 ;
2013-03-18 11:25:51 +01:00
spec - > gen . beep_nid = 0x01 ;
2011-07-07 18:23:21 +02:00
2013-02-19 18:23:31 +01:00
snd_hda_pick_fixup ( codec , alc260_fixup_models , alc260_fixup_tbl ,
alc260_fixups ) ;
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PRE_PROBE ) ;
2010-09-15 10:02:29 +02:00
2012-02-16 12:59:55 +01:00
/* automatic parse from the BIOS config */
err = alc260_parse_auto_config ( codec ) ;
if ( err < 0 )
goto error ;
2010-09-15 10:02:29 +02:00
2013-03-18 11:25:51 +01:00
if ( ! spec - > gen . no_analog )
2011-07-08 16:55:13 +02:00
set_beep_amp ( spec , 0x07 , 0x05 , HDA_INPUT ) ;
2010-09-15 10:02:29 +02:00
2011-07-07 18:23:21 +02:00
codec - > patch_ops = alc_patch_ops ;
spec - > shutup = alc_eapd_shutup ;
2011-04-15 10:11:12 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PROBE ) ;
2012-02-20 15:47:55 +01:00
2011-07-07 18:23:21 +02:00
return 0 ;
2011-10-17 16:39:09 +02:00
error :
alc_free ( codec ) ;
return err ;
2011-04-15 10:11:12 +02:00
}
2011-07-07 18:23:21 +02:00
/*
* ALC882 / 883 / 885 / 888 / 889 support
*
* ALC882 is almost identical with ALC880 but has cleaner and more flexible
* configuration . Each pin widget can choose any input DACs and a mixer .
* Each ADC is connected from a mixer of all inputs . This makes possible
* 6 - channel independent captures .
*
* In addition , an independent DAC for the multi - playback ( not used in this
* driver yet ) .
*/
/*
* Pin config fixes
*/
2010-04-12 08:59:25 +02:00
enum {
2011-11-07 17:59:13 +01:00
ALC882_FIXUP_ABIT_AW9D_MAX ,
ALC882_FIXUP_LENOVO_Y530 ,
ALC882_FIXUP_PB_M5210 ,
ALC882_FIXUP_ACER_ASPIRE_7736 ,
ALC882_FIXUP_ASUS_W90V ,
2012-03-05 21:33:23 +01:00
ALC889_FIXUP_CD ,
2011-11-07 17:59:13 +01:00
ALC889_FIXUP_VAIO_TT ,
2011-11-09 12:42:48 +01:00
ALC888_FIXUP_EEE1601 ,
2011-11-09 12:55:18 +01:00
ALC882_FIXUP_EAPD ,
2011-11-09 15:22:01 +01:00
ALC883_FIXUP_EAPD ,
2011-11-09 17:39:15 +01:00
ALC883_FIXUP_ACER_EAPD ,
2012-02-21 11:11:48 +01:00
ALC882_FIXUP_GPIO1 ,
ALC882_FIXUP_GPIO2 ,
2011-11-09 18:03:07 +01:00
ALC882_FIXUP_GPIO3 ,
2011-11-09 18:24:44 +01:00
ALC889_FIXUP_COEF ,
ALC882_FIXUP_ASUS_W2JC ,
2011-11-10 16:01:47 +01:00
ALC882_FIXUP_ACER_ASPIRE_4930G ,
ALC882_FIXUP_ACER_ASPIRE_8930G ,
ALC882_FIXUP_ASPIRE_8930G_VERBS ,
2011-11-14 17:42:11 +01:00
ALC885_FIXUP_MACPRO_GPIO ,
2012-02-13 15:25:07 +01:00
ALC889_FIXUP_DAC_ROUTE ,
2012-02-21 11:11:48 +01:00
ALC889_FIXUP_MBP_VREF ,
ALC889_FIXUP_IMAC91_VREF ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
ALC882_FIXUP_INV_DMIC ,
2012-07-29 10:04:08 +02:00
ALC882_FIXUP_NO_PRIMARY_HP ,
2010-04-12 08:59:25 +02:00
} ;
2011-11-09 18:24:44 +01:00
static void alc889_fixup_coef ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2011-11-09 18:24:44 +01:00
{
2013-01-10 09:52:52 +01:00
if ( action ! = HDA_FIXUP_ACT_INIT )
2011-11-09 18:24:44 +01:00
return ;
alc889_coef_init ( codec ) ;
}
2011-11-14 17:42:11 +01:00
/* toggle speaker-output according to the hp-jack state */
static void alc882_gpio_mute ( struct hda_codec * codec , int pin , int muted )
{
unsigned int gpiostate , gpiomask , gpiodir ;
gpiostate = snd_hda_codec_read ( codec , codec - > afg , 0 ,
AC_VERB_GET_GPIO_DATA , 0 ) ;
if ( ! muted )
gpiostate | = ( 1 < < pin ) ;
else
gpiostate & = ~ ( 1 < < pin ) ;
gpiomask = snd_hda_codec_read ( codec , codec - > afg , 0 ,
AC_VERB_GET_GPIO_MASK , 0 ) ;
gpiomask | = ( 1 < < pin ) ;
gpiodir = snd_hda_codec_read ( codec , codec - > afg , 0 ,
AC_VERB_GET_GPIO_DIRECTION , 0 ) ;
gpiodir | = ( 1 < < pin ) ;
snd_hda_codec_write ( codec , codec - > afg , 0 ,
AC_VERB_SET_GPIO_MASK , gpiomask ) ;
snd_hda_codec_write ( codec , codec - > afg , 0 ,
AC_VERB_SET_GPIO_DIRECTION , gpiodir ) ;
msleep ( 1 ) ;
snd_hda_codec_write ( codec , codec - > afg , 0 ,
AC_VERB_SET_GPIO_DATA , gpiostate ) ;
}
/* set up GPIO at initialization */
static void alc885_fixup_macpro_gpio ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2011-11-14 17:42:11 +01:00
{
2013-01-10 09:52:52 +01:00
if ( action ! = HDA_FIXUP_ACT_INIT )
2011-11-14 17:42:11 +01:00
return ;
alc882_gpio_mute ( codec , 0 , 0 ) ;
alc882_gpio_mute ( codec , 1 , 0 ) ;
}
2012-02-13 15:25:07 +01:00
/* Fix the connection of some pins for ALC889:
* At least , Acer Aspire 5935 shows the connections to DAC3 / 4 don ' t
* work correctly ( bko # 42740 )
*/
static void alc889_fixup_dac_route ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-02-13 15:25:07 +01:00
{
2013-01-10 09:52:52 +01:00
if ( action = = HDA_FIXUP_ACT_PRE_PROBE ) {
2012-02-17 10:12:38 +01:00
/* fake the connections during parsing the tree */
2012-02-13 15:25:07 +01:00
hda_nid_t conn1 [ 2 ] = { 0x0c , 0x0d } ;
hda_nid_t conn2 [ 2 ] = { 0x0e , 0x0f } ;
snd_hda_override_conn_list ( codec , 0x14 , 2 , conn1 ) ;
snd_hda_override_conn_list ( codec , 0x15 , 2 , conn1 ) ;
snd_hda_override_conn_list ( codec , 0x18 , 2 , conn2 ) ;
snd_hda_override_conn_list ( codec , 0x1a , 2 , conn2 ) ;
2013-01-10 09:52:52 +01:00
} else if ( action = = HDA_FIXUP_ACT_PROBE ) {
2012-02-17 10:12:38 +01:00
/* restore the connections */
hda_nid_t conn [ 5 ] = { 0x0c , 0x0d , 0x0e , 0x0f , 0x26 } ;
snd_hda_override_conn_list ( codec , 0x14 , 5 , conn ) ;
snd_hda_override_conn_list ( codec , 0x15 , 5 , conn ) ;
snd_hda_override_conn_list ( codec , 0x18 , 5 , conn ) ;
snd_hda_override_conn_list ( codec , 0x1a , 5 , conn ) ;
2012-02-13 15:25:07 +01:00
}
}
2012-02-21 11:11:48 +01:00
/* Set VREF on HP pin */
static void alc889_fixup_mbp_vref ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-02-21 11:11:48 +01:00
{
struct alc_spec * spec = codec - > spec ;
static hda_nid_t nids [ 2 ] = { 0x14 , 0x15 } ;
int i ;
2013-01-10 09:52:52 +01:00
if ( action ! = HDA_FIXUP_ACT_INIT )
2012-02-21 11:11:48 +01:00
return ;
for ( i = 0 ; i < ARRAY_SIZE ( nids ) ; i + + ) {
unsigned int val = snd_hda_codec_get_pincfg ( codec , nids [ i ] ) ;
if ( get_defcfg_device ( val ) ! = AC_JACK_HP_OUT )
continue ;
2013-01-10 10:12:22 +01:00
val = snd_hda_codec_get_pin_target ( codec , nids [ i ] ) ;
2012-02-21 11:11:48 +01:00
val | = AC_PINCTL_VREF_80 ;
2012-04-20 12:34:50 +02:00
snd_hda_set_pin_ctl ( codec , nids [ i ] , val ) ;
2012-12-19 15:22:24 +01:00
spec - > gen . keep_vref_in_automute = 1 ;
2012-02-21 11:11:48 +01:00
break ;
}
}
/* Set VREF on speaker pins on imac91 */
static void alc889_fixup_imac91_vref ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-02-21 11:11:48 +01:00
{
struct alc_spec * spec = codec - > spec ;
static hda_nid_t nids [ 2 ] = { 0x18 , 0x1a } ;
int i ;
2013-01-10 09:52:52 +01:00
if ( action ! = HDA_FIXUP_ACT_INIT )
2012-02-21 11:11:48 +01:00
return ;
for ( i = 0 ; i < ARRAY_SIZE ( nids ) ; i + + ) {
unsigned int val ;
2013-01-10 10:12:22 +01:00
val = snd_hda_codec_get_pin_target ( codec , nids [ i ] ) ;
2012-02-21 11:11:48 +01:00
val | = AC_PINCTL_VREF_50 ;
2012-04-20 12:34:50 +02:00
snd_hda_set_pin_ctl ( codec , nids [ i ] , val ) ;
2012-02-21 11:11:48 +01:00
}
2012-12-19 15:22:24 +01:00
spec - > gen . keep_vref_in_automute = 1 ;
2012-02-21 11:11:48 +01:00
}
2012-07-29 10:04:08 +02:00
/* Don't take HP output as primary
2013-02-12 16:49:46 +09:00
* Strangely , the speaker output doesn ' t work on Vaio Z and some Vaio
* all - in - one desktop PCs ( for example VGC - LN51JGB ) through DAC 0x05
2012-07-29 10:04:08 +02:00
*/
static void alc882_fixup_no_primary_hp ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-07-29 10:04:08 +02:00
{
struct alc_spec * spec = codec - > spec ;
2013-01-10 09:52:52 +01:00
if ( action = = HDA_FIXUP_ACT_PRE_PROBE )
2012-12-19 15:22:24 +01:00
spec - > gen . no_primary_hp = 1 ;
2012-07-29 10:04:08 +02:00
}
2013-01-10 09:52:52 +01:00
static const struct hda_fixup alc882_fixups [ ] = {
2011-11-07 17:59:13 +01:00
[ ALC882_FIXUP_ABIT_AW9D_MAX ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-07-07 18:23:21 +02:00
{ 0x15 , 0x01080104 } , /* side */
{ 0x16 , 0x01011012 } , /* rear */
{ 0x17 , 0x01016011 } , /* clfe */
2010-12-21 09:09:53 +01:00
{ }
2010-09-16 10:07:53 +02:00
}
} ,
2011-11-07 17:59:13 +01:00
[ ALC882_FIXUP_LENOVO_Y530 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-07-07 18:23:21 +02:00
{ 0x15 , 0x99130112 } , /* rear int speakers */
{ 0x16 , 0x99130111 } , /* subwoofer */
2010-12-15 09:18:18 +01:00
{ }
}
} ,
2011-11-07 17:59:13 +01:00
[ ALC882_FIXUP_PB_M5210 ] = {
2013-01-10 10:18:14 +01:00
. type = HDA_FIXUP_PINCTLS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
{ 0x19 , PIN_VREF50 } ,
2011-01-12 08:12:52 +01:00
{ }
}
} ,
2011-11-07 17:59:13 +01:00
[ ALC882_FIXUP_ACER_ASPIRE_7736 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-05-07 17:17:32 +02:00
. v . func = alc_fixup_sku_ignore ,
2011-04-15 10:11:12 +02:00
} ,
2011-11-07 17:59:13 +01:00
[ ALC882_FIXUP_ASUS_W90V ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-10-26 23:04:08 +02:00
{ 0x16 , 0x99130110 } , /* fix sequence for CLFE */
{ }
}
} ,
2012-03-05 21:33:23 +01:00
[ ALC889_FIXUP_CD ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-03-05 21:33:23 +01:00
{ 0x1c , 0x993301f0 } , /* CD */
{ }
}
} ,
2011-11-07 17:59:13 +01:00
[ ALC889_FIXUP_VAIO_TT ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-11-07 17:59:13 +01:00
{ 0x17 , 0x90170111 } , /* hidden surround speaker */
{ }
}
} ,
2011-11-09 12:42:48 +01:00
[ ALC888_FIXUP_EEE1601 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-09 12:42:48 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x0b } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x0838 } ,
{ }
}
2011-11-09 12:55:18 +01:00
} ,
[ ALC882_FIXUP_EAPD ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-09 12:55:18 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
/* change to EAPD mode */
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3060 } ,
{ }
}
} ,
2011-11-09 15:22:01 +01:00
[ ALC883_FIXUP_EAPD ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-09 15:22:01 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
/* change to EAPD mode */
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3070 } ,
{ }
}
} ,
2011-11-09 17:39:15 +01:00
[ ALC883_FIXUP_ACER_EAPD ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-09 17:39:15 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
/* eanable EAPD on Acer laptops */
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3050 } ,
{ }
}
} ,
2012-02-21 11:11:48 +01:00
[ ALC882_FIXUP_GPIO1 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2012-02-21 11:11:48 +01:00
. v . verbs = alc_gpio1_init_verbs ,
} ,
[ ALC882_FIXUP_GPIO2 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2012-02-21 11:11:48 +01:00
. v . verbs = alc_gpio2_init_verbs ,
} ,
2011-11-09 18:03:07 +01:00
[ ALC882_FIXUP_GPIO3 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-09 18:03:07 +01:00
. v . verbs = alc_gpio3_init_verbs ,
} ,
2011-11-09 18:24:44 +01:00
[ ALC882_FIXUP_ASUS_W2JC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-09 18:24:44 +01:00
. v . verbs = alc_gpio1_init_verbs ,
. chained = true ,
. chain_id = ALC882_FIXUP_EAPD ,
} ,
[ ALC889_FIXUP_COEF ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2011-11-09 18:24:44 +01:00
. v . func = alc889_fixup_coef ,
} ,
2011-11-10 16:01:47 +01:00
[ ALC882_FIXUP_ACER_ASPIRE_4930G ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-11-10 16:01:47 +01:00
{ 0x16 , 0x99130111 } , /* CLFE speaker */
{ 0x17 , 0x99130112 } , /* surround speaker */
{ }
2012-04-11 17:18:12 +02:00
} ,
. chained = true ,
. chain_id = ALC882_FIXUP_GPIO1 ,
2011-11-10 16:01:47 +01:00
} ,
[ ALC882_FIXUP_ACER_ASPIRE_8930G ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-11-10 16:01:47 +01:00
{ 0x16 , 0x99130111 } , /* CLFE speaker */
{ 0x1b , 0x99130112 } , /* surround speaker */
{ }
} ,
. chained = true ,
. chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS ,
} ,
[ ALC882_FIXUP_ASPIRE_8930G_VERBS ] = {
/* additional init verbs for Acer Aspire 8930G */
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-10 16:01:47 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
/* Enable all DACs */
/* DAC DISABLE/MUTE 1? */
/* setting bits 1-5 disables DAC nids 0x02-0x06
* apparently . Init = 0x38 */
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x03 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x0000 } ,
/* DAC DISABLE/MUTE 2? */
/* some bit here disables the other DACs.
* Init = 0x4900 */
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x08 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x0000 } ,
/* DMIC fix
* This laptop has a stereo digital microphone .
* The mics are only 1 cm apart which makes the stereo
* useless . However , either the mic or the ALC889
* makes the signal become a difference / sum signal
* instead of standard stereo , which is annoying .
* So instead we flip this bit which makes the
* codec replicate the sum signal to both channels ,
* turning it into a normal mono mic .
*/
/* DMIC_CONTROL? Init value = 0x0001 */
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x0b } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x0003 } ,
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3050 } ,
{ }
2012-04-11 17:18:12 +02:00
} ,
. chained = true ,
. chain_id = ALC882_FIXUP_GPIO1 ,
2011-11-10 16:01:47 +01:00
} ,
2011-11-14 17:42:11 +01:00
[ ALC885_FIXUP_MACPRO_GPIO ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2011-11-14 17:42:11 +01:00
. v . func = alc885_fixup_macpro_gpio ,
} ,
2012-02-13 15:25:07 +01:00
[ ALC889_FIXUP_DAC_ROUTE ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-02-13 15:25:07 +01:00
. v . func = alc889_fixup_dac_route ,
} ,
2012-02-21 11:11:48 +01:00
[ ALC889_FIXUP_MBP_VREF ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-02-21 11:11:48 +01:00
. v . func = alc889_fixup_mbp_vref ,
. chained = true ,
. chain_id = ALC882_FIXUP_GPIO1 ,
} ,
[ ALC889_FIXUP_IMAC91_VREF ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-02-21 11:11:48 +01:00
. v . func = alc889_fixup_imac91_vref ,
. chained = true ,
. chain_id = ALC882_FIXUP_GPIO1 ,
} ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
[ ALC882_FIXUP_INV_DMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
. v . func = alc_fixup_inv_dmic_0x12 ,
} ,
2012-07-29 10:04:08 +02:00
[ ALC882_FIXUP_NO_PRIMARY_HP ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-07-29 10:04:08 +02:00
. v . func = alc882_fixup_no_primary_hp ,
} ,
2010-04-12 08:59:25 +02:00
} ;
2011-07-07 18:23:21 +02:00
static const struct snd_pci_quirk alc882_fixup_tbl [ ] = {
2011-11-09 17:39:15 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x006c , " Acer Aspire 9810 " , ALC883_FIXUP_ACER_EAPD ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0090 , " Acer Aspire " , ALC883_FIXUP_ACER_EAPD ) ,
SND_PCI_QUIRK ( 0x1025 , 0x010a , " Acer Ferrari 5000 " , ALC883_FIXUP_ACER_EAPD ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0110 , " Acer Aspire " , ALC883_FIXUP_ACER_EAPD ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0112 , " Acer Aspire 9303 " , ALC883_FIXUP_ACER_EAPD ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0121 , " Acer Aspire 5920G " , ALC883_FIXUP_ACER_EAPD ) ,
2011-11-10 16:01:47 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x013e , " Acer Aspire 4930G " ,
ALC882_FIXUP_ACER_ASPIRE_4930G ) ,
SND_PCI_QUIRK ( 0x1025 , 0x013f , " Acer Aspire 5930G " ,
ALC882_FIXUP_ACER_ASPIRE_4930G ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0145 , " Acer Aspire 8930G " ,
ALC882_FIXUP_ACER_ASPIRE_8930G ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0146 , " Acer Aspire 6935G " ,
ALC882_FIXUP_ACER_ASPIRE_8930G ) ,
SND_PCI_QUIRK ( 0x1025 , 0x015e , " Acer Aspire 6930G " ,
ALC882_FIXUP_ACER_ASPIRE_4930G ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0166 , " Acer Aspire 6530G " ,
ALC882_FIXUP_ACER_ASPIRE_4930G ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0142 , " Acer Aspire 7730G " ,
ALC882_FIXUP_ACER_ASPIRE_4930G ) ,
2011-11-07 17:59:13 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x0155 , " Packard-Bell M5120 " , ALC882_FIXUP_PB_M5210 ) ,
2012-05-07 10:07:33 +02:00
SND_PCI_QUIRK ( 0x1025 , 0x021e , " Acer Aspire 5739G " ,
ALC882_FIXUP_ACER_ASPIRE_4930G ) ,
2012-02-13 15:25:07 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x0259 , " Acer Aspire 5935 " , ALC889_FIXUP_DAC_ROUTE ) ,
2012-04-12 08:00:19 +02:00
SND_PCI_QUIRK ( 0x1025 , 0x026b , " Acer Aspire 8940G " , ALC882_FIXUP_ACER_ASPIRE_8930G ) ,
2011-11-09 17:45:55 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x0296 , " Acer Aspire 7736z " , ALC882_FIXUP_ACER_ASPIRE_7736 ) ,
2011-11-09 12:55:18 +01:00
SND_PCI_QUIRK ( 0x1043 , 0x13c2 , " Asus A7M " , ALC882_FIXUP_EAPD ) ,
2011-11-07 17:59:13 +01:00
SND_PCI_QUIRK ( 0x1043 , 0x1873 , " ASUS W90V " , ALC882_FIXUP_ASUS_W90V ) ,
2011-11-09 18:24:44 +01:00
SND_PCI_QUIRK ( 0x1043 , 0x1971 , " Asus W2JC " , ALC882_FIXUP_ASUS_W2JC ) ,
2011-11-09 12:42:48 +01:00
SND_PCI_QUIRK ( 0x1043 , 0x835f , " Asus Eee 1601 " , ALC888_FIXUP_EEE1601 ) ,
2011-11-09 17:45:55 +01:00
SND_PCI_QUIRK ( 0x104d , 0x9047 , " Sony Vaio TT " , ALC889_FIXUP_VAIO_TT ) ,
2012-07-29 10:04:08 +02:00
SND_PCI_QUIRK ( 0x104d , 0x905a , " Sony Vaio Z " , ALC882_FIXUP_NO_PRIMARY_HP ) ,
2013-02-12 16:47:44 +09:00
SND_PCI_QUIRK ( 0x104d , 0x9043 , " Sony Vaio VGC-LN51JGB " , ALC882_FIXUP_NO_PRIMARY_HP ) ,
2011-11-14 17:42:11 +01:00
/* All Apple entries are in codec SSIDs */
2012-02-21 11:11:48 +01:00
SND_PCI_QUIRK ( 0x106b , 0x00a0 , " MacBookPro 3,1 " , ALC889_FIXUP_MBP_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x00a1 , " Macbook " , ALC889_FIXUP_MBP_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x00a4 , " MacbookPro 4,1 " , ALC889_FIXUP_MBP_VREF ) ,
2011-11-14 17:42:11 +01:00
SND_PCI_QUIRK ( 0x106b , 0x0c00 , " Mac Pro " , ALC885_FIXUP_MACPRO_GPIO ) ,
SND_PCI_QUIRK ( 0x106b , 0x1000 , " iMac 24 " , ALC885_FIXUP_MACPRO_GPIO ) ,
SND_PCI_QUIRK ( 0x106b , 0x2800 , " AppleTV " , ALC885_FIXUP_MACPRO_GPIO ) ,
2012-02-21 11:11:48 +01:00
SND_PCI_QUIRK ( 0x106b , 0x2c00 , " MacbookPro rev3 " , ALC889_FIXUP_MBP_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x3000 , " iMac " , ALC889_FIXUP_MBP_VREF ) ,
2011-11-14 17:42:11 +01:00
SND_PCI_QUIRK ( 0x106b , 0x3200 , " iMac 7,1 Aluminum " , ALC882_FIXUP_EAPD ) ,
2012-02-21 11:11:48 +01:00
SND_PCI_QUIRK ( 0x106b , 0x3400 , " MacBookAir 1,1 " , ALC889_FIXUP_MBP_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x3500 , " MacBookAir 2,1 " , ALC889_FIXUP_MBP_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x3600 , " Macbook 3,1 " , ALC889_FIXUP_MBP_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x3800 , " MacbookPro 4,1 " , ALC889_FIXUP_MBP_VREF ) ,
2011-11-14 17:42:11 +01:00
SND_PCI_QUIRK ( 0x106b , 0x3e00 , " iMac 24 Aluminum " , ALC885_FIXUP_MACPRO_GPIO ) ,
2012-02-21 11:11:48 +01:00
SND_PCI_QUIRK ( 0x106b , 0x3f00 , " Macbook 5,1 " , ALC889_FIXUP_IMAC91_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x4000 , " MacbookPro 5,1 " , ALC889_FIXUP_IMAC91_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x4100 , " Macmini 3,1 " , ALC889_FIXUP_IMAC91_VREF ) ,
2012-04-12 13:55:36 -04:00
SND_PCI_QUIRK ( 0x106b , 0x4200 , " Mac Pro 5,1 " , ALC885_FIXUP_MACPRO_GPIO ) ,
2012-11-12 10:07:36 +01:00
SND_PCI_QUIRK ( 0x106b , 0x4300 , " iMac 9,1 " , ALC889_FIXUP_IMAC91_VREF ) ,
2012-02-21 11:11:48 +01:00
SND_PCI_QUIRK ( 0x106b , 0x4600 , " MacbookPro 5,2 " , ALC889_FIXUP_IMAC91_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x4900 , " iMac 9,1 Aluminum " , ALC889_FIXUP_IMAC91_VREF ) ,
SND_PCI_QUIRK ( 0x106b , 0x4a00 , " Macbook 5,2 " , ALC889_FIXUP_IMAC91_VREF ) ,
2011-11-14 17:42:11 +01:00
2011-11-09 15:22:01 +01:00
SND_PCI_QUIRK ( 0x1071 , 0x8258 , " Evesham Voyaeger " , ALC882_FIXUP_EAPD ) ,
2012-05-07 11:13:14 +02:00
SND_PCI_QUIRK ( 0x1462 , 0x7350 , " MSI-7350 " , ALC889_FIXUP_CD ) ,
2011-11-09 18:03:07 +01:00
SND_PCI_QUIRK_VENDOR ( 0x1462 , " MSI " , ALC882_FIXUP_GPIO3 ) ,
2012-03-05 21:33:23 +01:00
SND_PCI_QUIRK ( 0x1458 , 0xa002 , " Gigabyte EP45-DS3 " , ALC889_FIXUP_CD ) ,
2011-11-07 17:59:13 +01:00
SND_PCI_QUIRK ( 0x147b , 0x107a , " Abit AW9D-MAX " , ALC882_FIXUP_ABIT_AW9D_MAX ) ,
2011-11-09 15:22:01 +01:00
SND_PCI_QUIRK_VENDOR ( 0x1558 , " Clevo laptop " , ALC882_FIXUP_EAPD ) ,
SND_PCI_QUIRK ( 0x161f , 0x2054 , " Medion laptop " , ALC883_FIXUP_EAPD ) ,
2011-11-09 17:45:55 +01:00
SND_PCI_QUIRK ( 0x17aa , 0x3a0d , " Lenovo Y530 " , ALC882_FIXUP_LENOVO_Y530 ) ,
2011-11-09 18:24:44 +01:00
SND_PCI_QUIRK ( 0x8086 , 0x0022 , " DX58SO " , ALC889_FIXUP_COEF ) ,
2010-04-12 08:59:25 +02:00
{ }
} ;
2013-01-10 09:52:52 +01:00
static const struct hda_model_fixup alc882_fixup_models [ ] = {
2012-04-11 14:03:41 +02:00
{ . id = ALC882_FIXUP_ACER_ASPIRE_4930G , . name = " acer-aspire-4930g " } ,
{ . id = ALC882_FIXUP_ACER_ASPIRE_8930G , . name = " acer-aspire-8930g " } ,
{ . id = ALC883_FIXUP_ACER_EAPD , . name = " acer-aspire " } ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
{ . id = ALC882_FIXUP_INV_DMIC , . name = " inv-dmic " } ,
2012-07-29 10:04:08 +02:00
{ . id = ALC882_FIXUP_NO_PRIMARY_HP , . name = " no-primary-hp " } ,
2012-04-11 14:03:41 +02:00
{ }
} ;
2007-12-13 16:52:54 +01:00
/*
2011-07-07 18:23:21 +02:00
* BIOS auto configuration
2007-12-13 16:52:54 +01:00
*/
2011-07-07 18:23:21 +02:00
/* almost identical with ALC880 parser... */
static int alc882_parse_auto_config ( struct hda_codec * codec )
{
static const hda_nid_t alc882_ignore [ ] = { 0x1d , 0 } ;
2011-07-08 16:55:13 +02:00
static const hda_nid_t alc882_ssids [ ] = { 0x15 , 0x1b , 0x14 , 0 } ;
return alc_parse_auto_config ( codec , alc882_ignore , alc882_ssids ) ;
2011-07-07 18:23:21 +02:00
}
2011-05-18 11:53:16 +02:00
2011-07-07 18:23:21 +02:00
/*
*/
static int patch_alc882 ( struct hda_codec * codec )
2007-12-13 16:52:54 +01:00
{
struct alc_spec * spec ;
2012-02-21 11:11:48 +01:00
int err ;
2007-12-13 16:52:54 +01:00
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0x0b ) ;
if ( err < 0 )
return err ;
2007-12-13 16:52:54 +01:00
2012-05-07 18:03:15 +02:00
spec = codec - > spec ;
2011-06-27 10:52:59 +02:00
2011-07-07 18:23:21 +02:00
switch ( codec - > vendor_id ) {
case 0x10ec0882 :
case 0x10ec0885 :
break ;
default :
/* ALC883 and variants */
alc_fix_pll_init ( codec , 0x20 , 0x0a , 10 ) ;
break ;
2010-12-21 09:14:13 +01:00
}
2010-09-15 10:02:29 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_pick_fixup ( codec , alc882_fixup_models , alc882_fixup_tbl ,
2012-04-11 14:03:41 +02:00
alc882_fixups ) ;
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PRE_PROBE ) ;
2010-04-12 08:59:25 +02:00
2011-07-07 18:23:21 +02:00
alc_auto_parse_customize_define ( codec ) ;
2013-03-18 11:25:51 +01:00
if ( has_cdefine_beep ( codec ) )
spec - > gen . beep_nid = 0x01 ;
2012-02-21 11:11:48 +01:00
/* automatic parse from the BIOS config */
err = alc882_parse_auto_config ( codec ) ;
if ( err < 0 )
goto error ;
2007-12-13 16:52:54 +01:00
2013-03-18 11:25:51 +01:00
if ( ! spec - > gen . no_analog & & spec - > gen . beep_nid )
2011-07-07 18:23:21 +02:00
set_beep_amp ( spec , 0x0b , 0x05 , HDA_INPUT ) ;
2007-12-13 16:52:54 +01:00
codec - > patch_ops = alc_patch_ops ;
2010-10-21 08:49:56 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PROBE ) ;
2012-02-20 15:47:55 +01:00
2007-12-13 16:52:54 +01:00
return 0 ;
2011-10-17 16:39:09 +02:00
error :
alc_free ( codec ) ;
return err ;
2007-12-13 16:52:54 +01:00
}
2005-12-05 19:42:22 +01:00
/*
2011-07-07 18:23:21 +02:00
* ALC262 support
2005-12-05 19:42:22 +01:00
*/
2011-07-07 18:23:21 +02:00
static int alc262_parse_auto_config ( struct hda_codec * codec )
2005-12-05 19:42:22 +01:00
{
2011-07-07 18:23:21 +02:00
static const hda_nid_t alc262_ignore [ ] = { 0x1d , 0 } ;
2011-07-08 16:55:13 +02:00
static const hda_nid_t alc262_ssids [ ] = { 0x15 , 0x1b , 0x14 , 0 } ;
return alc_parse_auto_config ( codec , alc262_ignore , alc262_ssids ) ;
2005-12-05 19:42:22 +01:00
}
/*
2011-07-07 18:23:21 +02:00
* Pin config fixes
2005-12-05 19:42:22 +01:00
*/
2009-12-01 12:19:37 +01:00
enum {
2011-11-07 12:23:55 +01:00
ALC262_FIXUP_FSC_H270 ,
2013-01-18 15:41:34 +01:00
ALC262_FIXUP_FSC_S7110 ,
2011-11-07 12:23:55 +01:00
ALC262_FIXUP_HP_Z200 ,
ALC262_FIXUP_TYAN ,
2011-11-07 14:20:07 +01:00
ALC262_FIXUP_LENOVO_3000 ,
2011-11-07 14:41:01 +01:00
ALC262_FIXUP_BENQ ,
ALC262_FIXUP_BENQ_T31 ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
ALC262_FIXUP_INV_DMIC ,
2009-12-01 12:19:37 +01:00
} ;
2013-01-10 09:52:52 +01:00
static const struct hda_fixup alc262_fixups [ ] = {
2011-11-07 12:23:55 +01:00
[ ALC262_FIXUP_FSC_H270 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-07-07 18:23:21 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x15 , 0x0221142f } , /* front HP */
{ 0x1b , 0x0121141f } , /* rear HP */
{ }
}
} ,
2013-01-18 15:41:34 +01:00
[ ALC262_FIXUP_FSC_S7110 ] = {
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
{ 0x15 , 0x90170110 } , /* speaker */
{ }
} ,
. chained = true ,
. chain_id = ALC262_FIXUP_BENQ ,
} ,
2011-11-07 12:23:55 +01:00
[ ALC262_FIXUP_HP_Z200 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-07-07 18:23:21 +02:00
{ 0x16 , 0x99130120 } , /* internal speaker */
2010-08-30 09:39:57 +02:00
{ }
}
2009-12-01 12:19:37 +01:00
} ,
2011-11-07 12:23:55 +01:00
[ ALC262_FIXUP_TYAN ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-11-07 12:23:55 +01:00
{ 0x14 , 0x1993e1f0 } , /* int AUX */
{ }
}
} ,
2011-11-07 14:20:07 +01:00
[ ALC262_FIXUP_LENOVO_3000 ] = {
2013-01-10 10:18:14 +01:00
. type = HDA_FIXUP_PINCTLS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
{ 0x19 , PIN_VREF50 } ,
2011-11-07 14:41:01 +01:00
{ }
} ,
. chained = true ,
. chain_id = ALC262_FIXUP_BENQ ,
} ,
[ ALC262_FIXUP_BENQ ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-07 14:41:01 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
2011-11-07 14:20:07 +01:00
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3070 } ,
{ }
}
} ,
2011-11-07 14:41:01 +01:00
[ ALC262_FIXUP_BENQ_T31 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-11-07 14:41:01 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x07 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x3050 } ,
{ }
}
} ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
[ ALC262_FIXUP_INV_DMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
. v . func = alc_fixup_inv_dmic_0x12 ,
} ,
2009-12-01 12:19:37 +01:00
} ;
2011-07-07 18:23:21 +02:00
static const struct snd_pci_quirk alc262_fixup_tbl [ ] = {
2011-11-07 12:23:55 +01:00
SND_PCI_QUIRK ( 0x103c , 0x170b , " HP Z200 " , ALC262_FIXUP_HP_Z200 ) ,
2013-01-18 15:41:34 +01:00
SND_PCI_QUIRK ( 0x10cf , 0x1397 , " Fujitsu Lifebook S7110 " , ALC262_FIXUP_FSC_S7110 ) ,
2011-11-07 14:59:40 +01:00
SND_PCI_QUIRK ( 0x10cf , 0x142d , " Fujitsu Lifebook E8410 " , ALC262_FIXUP_BENQ ) ,
2011-11-07 12:23:55 +01:00
SND_PCI_QUIRK ( 0x10f1 , 0x2915 , " Tyan Thunder n6650W " , ALC262_FIXUP_TYAN ) ,
SND_PCI_QUIRK ( 0x1734 , 0x1147 , " FSC Celsius H270 " , ALC262_FIXUP_FSC_H270 ) ,
2011-11-07 14:20:07 +01:00
SND_PCI_QUIRK ( 0x17aa , 0x384e , " Lenovo 3000 " , ALC262_FIXUP_LENOVO_3000 ) ,
2011-11-07 14:41:01 +01:00
SND_PCI_QUIRK ( 0x17ff , 0x0560 , " Benq ED8 " , ALC262_FIXUP_BENQ ) ,
SND_PCI_QUIRK ( 0x17ff , 0x058d , " Benq T31-16 " , ALC262_FIXUP_BENQ_T31 ) ,
2009-12-01 12:19:37 +01:00
{ }
} ;
2005-12-05 19:42:22 +01:00
2013-01-10 09:52:52 +01:00
static const struct hda_model_fixup alc262_fixup_models [ ] = {
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
{ . id = ALC262_FIXUP_INV_DMIC , . name = " inv-dmic " } ,
{ }
} ;
2011-07-07 18:23:21 +02:00
/*
*/
static int patch_alc262 ( struct hda_codec * codec )
2005-12-05 19:42:22 +01:00
{
struct alc_spec * spec ;
int err ;
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0x0b ) ;
if ( err < 0 )
return err ;
2005-12-05 19:42:22 +01:00
2012-05-07 18:03:15 +02:00
spec = codec - > spec ;
2012-12-19 15:22:24 +01:00
spec - > gen . shared_mic_vref_pin = 0x18 ;
2011-07-07 18:23:21 +02:00
#if 0
/* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
* under - run
*/
{
int tmp ;
snd_hda_codec_write ( codec , 0x1a , 0 , AC_VERB_SET_COEF_INDEX , 7 ) ;
tmp = snd_hda_codec_read ( codec , 0x20 , 0 , AC_VERB_GET_PROC_COEF , 0 ) ;
snd_hda_codec_write ( codec , 0x1a , 0 , AC_VERB_SET_COEF_INDEX , 7 ) ;
snd_hda_codec_write ( codec , 0x1a , 0 , AC_VERB_SET_PROC_COEF , tmp | 0x80 ) ;
}
# endif
alc_fix_pll_init ( codec , 0x20 , 0x0a , 10 ) ;
2013-01-10 09:52:52 +01:00
snd_hda_pick_fixup ( codec , alc262_fixup_models , alc262_fixup_tbl ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
alc262_fixups ) ;
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PRE_PROBE ) ;
2006-06-28 15:08:22 +02:00
2012-05-07 18:09:48 +02:00
alc_auto_parse_customize_define ( codec ) ;
2013-03-18 11:25:51 +01:00
if ( has_cdefine_beep ( codec ) )
spec - > gen . beep_nid = 0x01 ;
2011-11-07 17:18:44 +01:00
/* automatic parse from the BIOS config */
err = alc262_parse_auto_config ( codec ) ;
if ( err < 0 )
goto error ;
2005-12-05 19:42:22 +01:00
2013-03-18 11:25:51 +01:00
if ( ! spec - > gen . no_analog & & spec - > gen . beep_nid )
2011-07-07 18:23:21 +02:00
set_beep_amp ( spec , 0x0b , 0x05 , HDA_INPUT ) ;
2008-01-10 16:53:55 +01:00
2005-12-05 19:42:22 +01:00
codec - > patch_ops = alc_patch_ops ;
2011-07-07 18:23:21 +02:00
spec - > shutup = alc_eapd_shutup ;
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PROBE ) ;
2012-02-20 15:47:55 +01:00
2005-04-16 15:20:36 -07:00
return 0 ;
2011-10-17 16:39:09 +02:00
error :
alc_free ( codec ) ;
return err ;
2005-04-16 15:20:36 -07:00
}
2007-02-02 18:17:27 +01:00
/*
2011-07-07 18:23:21 +02:00
* ALC268
2007-02-02 18:17:27 +01:00
*/
2011-07-07 18:23:21 +02:00
/* bind Beep switches of both NID 0x0f and 0x10 */
static const struct hda_bind_ctls alc268_bind_beep_sw = {
. ops = & snd_hda_bind_sw ,
. values = {
HDA_COMPOSE_AMP_VAL ( 0x0f , 3 , 1 , HDA_INPUT ) ,
HDA_COMPOSE_AMP_VAL ( 0x10 , 3 , 1 , HDA_INPUT ) ,
0
} ,
2007-02-02 18:17:27 +01:00
} ;
2011-07-07 18:23:21 +02:00
static const struct snd_kcontrol_new alc268_beep_mixer [ ] = {
HDA_CODEC_VOLUME ( " Beep Playback Volume " , 0x1d , 0x0 , HDA_INPUT ) ,
HDA_BIND_SW ( " Beep Playback Switch " , & alc268_bind_beep_sw ) ,
{ }
2007-02-02 18:17:27 +01:00
} ;
2011-07-07 18:23:21 +02:00
/* set PCBEEP vol = 0, mute connections */
static const struct hda_verb alc268_beep_init_verbs [ ] = {
{ 0x1d , AC_VERB_SET_AMP_GAIN_MUTE , AMP_IN_UNMUTE ( 0 ) } ,
{ 0x0f , AC_VERB_SET_AMP_GAIN_MUTE , AMP_IN_MUTE ( 1 ) } ,
{ 0x10 , AC_VERB_SET_AMP_GAIN_MUTE , AMP_IN_MUTE ( 1 ) } ,
{ }
2007-02-02 18:17:27 +01:00
} ;
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
enum {
ALC268_FIXUP_INV_DMIC ,
2012-10-20 10:55:21 +02:00
ALC268_FIXUP_HP_EAPD ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
} ;
2013-01-10 09:52:52 +01:00
static const struct hda_fixup alc268_fixups [ ] = {
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
[ ALC268_FIXUP_INV_DMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
. v . func = alc_fixup_inv_dmic_0x12 ,
} ,
2012-10-20 10:55:21 +02:00
[ ALC268_FIXUP_HP_EAPD ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2012-10-20 10:55:21 +02:00
. v . verbs = ( const struct hda_verb [ ] ) {
{ 0x15 , AC_VERB_SET_EAPD_BTLENABLE , 0 } ,
{ }
}
} ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
} ;
2013-01-10 09:52:52 +01:00
static const struct hda_model_fixup alc268_fixup_models [ ] = {
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
{ . id = ALC268_FIXUP_INV_DMIC , . name = " inv-dmic " } ,
2012-10-20 10:55:21 +02:00
{ . id = ALC268_FIXUP_HP_EAPD , . name = " hp-eapd " } ,
{ }
} ;
static const struct snd_pci_quirk alc268_fixup_tbl [ ] = {
2013-01-28 05:45:47 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x015b , " Acer AOA 150 (ZG5) " , ALC268_FIXUP_INV_DMIC ) ,
2012-10-20 10:55:21 +02:00
/* below is codec SSID since multiple Toshiba laptops have the
* same PCI SSID 1179 : ff00
*/
SND_PCI_QUIRK ( 0x1179 , 0xff06 , " Toshiba P200 " , ALC268_FIXUP_HP_EAPD ) ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
{ }
} ;
2007-02-02 18:17:27 +01:00
/*
* BIOS auto configuration
*/
2011-07-07 18:23:21 +02:00
static int alc268_parse_auto_config ( struct hda_codec * codec )
2007-02-02 18:17:27 +01:00
{
2011-07-08 16:55:13 +02:00
static const hda_nid_t alc268_ssids [ ] = { 0x15 , 0x1b , 0x14 , 0 } ;
2013-03-18 11:25:51 +01:00
return alc_parse_auto_config ( codec , NULL , alc268_ssids ) ;
2007-02-02 18:17:27 +01:00
}
2011-07-07 18:23:21 +02:00
/*
*/
static int patch_alc268 ( struct hda_codec * codec )
2007-02-02 18:17:27 +01:00
{
struct alc_spec * spec ;
2013-03-18 11:25:51 +01:00
int err ;
2007-02-02 18:17:27 +01:00
2011-07-07 18:23:21 +02:00
/* ALC268 has no aa-loopback mixer */
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0 ) ;
if ( err < 0 )
return err ;
spec = codec - > spec ;
2013-03-18 11:25:51 +01:00
spec - > gen . beep_nid = 0x01 ;
2011-06-27 10:52:59 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_pick_fixup ( codec , alc268_fixup_models , alc268_fixup_tbl , alc268_fixups ) ;
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PRE_PROBE ) ;
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
2011-08-16 15:15:40 +02:00
/* automatic parse from the BIOS config */
err = alc268_parse_auto_config ( codec ) ;
2011-10-17 16:39:09 +02:00
if ( err < 0 )
goto error ;
2007-02-02 18:17:27 +01:00
2013-03-18 11:25:51 +01:00
if ( err > 0 & & ! spec - > gen . no_analog & &
spec - > gen . autocfg . speaker_pins [ 0 ] ! = 0x1d ) {
add_mixer ( spec , alc268_beep_mixer ) ;
snd_hda_add_verbs ( codec , alc268_beep_init_verbs ) ;
2011-07-07 18:23:21 +02:00
if ( ! query_amp_caps ( codec , 0x1d , HDA_INPUT ) )
/* override the amp caps for beep generator */
snd_hda_override_amp_caps ( codec , 0x1d , HDA_INPUT ,
( 0x0c < < AC_AMPCAP_OFFSET_SHIFT ) |
( 0x0c < < AC_AMPCAP_NUM_STEPS_SHIFT ) |
( 0x07 < < AC_AMPCAP_STEP_SIZE_SHIFT ) |
( 0 < < AC_AMPCAP_MUTE_SHIFT ) ) ;
2008-05-27 12:14:47 +02:00
}
2007-02-02 18:17:27 +01:00
codec - > patch_ops = alc_patch_ops ;
2011-04-07 10:37:16 +02:00
spec - > shutup = alc_eapd_shutup ;
2011-07-07 18:23:21 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PROBE ) ;
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
2007-02-02 18:17:27 +01:00
return 0 ;
2011-10-17 16:39:09 +02:00
error :
alc_free ( codec ) ;
return err ;
2007-02-02 18:17:27 +01:00
}
2007-04-12 13:06:07 +02:00
/*
2011-07-07 18:23:21 +02:00
* ALC269
2007-04-12 13:06:07 +02:00
*/
2012-12-19 15:22:24 +01:00
static int playback_pcm_open ( struct hda_pcm_stream * hinfo ,
struct hda_codec * codec ,
struct snd_pcm_substream * substream )
{
struct hda_gen_spec * spec = codec - > spec ;
return snd_hda_multi_out_analog_open ( codec , & spec - > multiout , substream ,
hinfo ) ;
}
static int playback_pcm_prepare ( struct hda_pcm_stream * hinfo ,
struct hda_codec * codec ,
unsigned int stream_tag ,
unsigned int format ,
struct snd_pcm_substream * substream )
{
struct hda_gen_spec * spec = codec - > spec ;
return snd_hda_multi_out_analog_prepare ( codec , & spec - > multiout ,
stream_tag , format , substream ) ;
}
static int playback_pcm_cleanup ( struct hda_pcm_stream * hinfo ,
struct hda_codec * codec ,
struct snd_pcm_substream * substream )
{
struct hda_gen_spec * spec = codec - > spec ;
return snd_hda_multi_out_analog_cleanup ( codec , & spec - > multiout ) ;
}
2011-07-07 18:23:21 +02:00
static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
. substreams = 1 ,
. channels_min = 2 ,
. channels_max = 8 ,
. rates = SNDRV_PCM_RATE_44100 , /* fixed rate */
/* NID is set in alc_build_pcms */
. ops = {
2012-12-19 15:22:24 +01:00
. open = playback_pcm_open ,
. prepare = playback_pcm_prepare ,
. cleanup = playback_pcm_cleanup
2007-04-12 13:06:07 +02:00
} ,
} ;
2011-07-07 18:23:21 +02:00
static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
. substreams = 1 ,
. channels_min = 2 ,
. channels_max = 2 ,
. rates = SNDRV_PCM_RATE_44100 , /* fixed rate */
/* NID is set in alc_build_pcms */
2007-04-12 13:06:07 +02:00
} ;
2007-10-16 14:28:03 +02:00
2011-07-07 18:23:21 +02:00
/* different alc269-variants */
enum {
ALC269_TYPE_ALC269VA ,
ALC269_TYPE_ALC269VB ,
ALC269_TYPE_ALC269VC ,
2012-05-25 08:08:38 +02:00
ALC269_TYPE_ALC269VD ,
2013-01-10 10:25:48 +01:00
ALC269_TYPE_ALC280 ,
ALC269_TYPE_ALC282 ,
ALC269_TYPE_ALC284 ,
2007-04-12 13:06:07 +02:00
} ;
/*
2011-07-07 18:23:21 +02:00
* BIOS auto configuration
2007-04-12 13:06:07 +02:00
*/
2011-07-07 18:23:21 +02:00
static int alc269_parse_auto_config ( struct hda_codec * codec )
{
static const hda_nid_t alc269_ignore [ ] = { 0x1d , 0 } ;
2011-07-08 16:55:13 +02:00
static const hda_nid_t alc269_ssids [ ] = { 0 , 0x1b , 0x14 , 0x21 } ;
static const hda_nid_t alc269va_ssids [ ] = { 0x15 , 0x1b , 0x14 , 0 } ;
struct alc_spec * spec = codec - > spec ;
2012-05-25 08:08:38 +02:00
const hda_nid_t * ssids ;
switch ( spec - > codec_variant ) {
case ALC269_TYPE_ALC269VA :
case ALC269_TYPE_ALC269VC :
2013-01-10 10:25:48 +01:00
case ALC269_TYPE_ALC280 :
case ALC269_TYPE_ALC284 :
2012-05-25 08:08:38 +02:00
ssids = alc269va_ssids ;
break ;
case ALC269_TYPE_ALC269VB :
case ALC269_TYPE_ALC269VD :
2013-01-10 10:25:48 +01:00
case ALC269_TYPE_ALC282 :
2012-05-25 08:08:38 +02:00
ssids = alc269_ssids ;
break ;
default :
ssids = alc269_ssids ;
break ;
}
2007-04-12 13:06:07 +02:00
2011-07-08 16:55:13 +02:00
return alc_parse_auto_config ( codec , alc269_ignore , ssids ) ;
2011-07-07 18:23:21 +02:00
}
2007-04-12 13:06:07 +02:00
2012-11-08 10:23:18 +01:00
static void alc269vb_toggle_power_output ( struct hda_codec * codec , int power_up )
2011-07-07 18:23:21 +02:00
{
int val = alc_read_coef_idx ( codec , 0x04 ) ;
if ( power_up )
val | = 1 < < 11 ;
else
val & = ~ ( 1 < < 11 ) ;
alc_write_coef_idx ( codec , 0x04 , val ) ;
}
2007-10-16 14:28:03 +02:00
2011-07-07 18:23:21 +02:00
static void alc269_shutup ( struct hda_codec * codec )
{
2012-05-25 08:08:38 +02:00
struct alc_spec * spec = codec - > spec ;
if ( spec - > codec_variant ! = ALC269_TYPE_ALC269VB )
return ;
2012-11-08 10:23:18 +01:00
if ( spec - > codec_variant = = ALC269_TYPE_ALC269VB )
alc269vb_toggle_power_output ( codec , 0 ) ;
if ( spec - > codec_variant = = ALC269_TYPE_ALC269VB & &
( alc_get_coef0 ( codec ) & 0x00ff ) = = 0x018 ) {
2011-07-07 18:23:21 +02:00
msleep ( 150 ) ;
}
}
2007-10-16 14:28:03 +02:00
2011-07-26 09:52:50 +02:00
# ifdef CONFIG_PM
2011-07-07 18:23:21 +02:00
static int alc269_resume ( struct hda_codec * codec )
{
2012-05-25 08:08:38 +02:00
struct alc_spec * spec = codec - > spec ;
2012-11-08 10:23:18 +01:00
if ( spec - > codec_variant = = ALC269_TYPE_ALC269VB )
alc269vb_toggle_power_output ( codec , 0 ) ;
if ( spec - > codec_variant = = ALC269_TYPE_ALC269VB & &
2012-05-25 08:08:38 +02:00
( alc_get_coef0 ( codec ) & 0x00ff ) = = 0x018 ) {
2011-07-07 18:23:21 +02:00
msleep ( 150 ) ;
}
2008-01-10 13:03:59 +01:00
2011-07-07 18:23:21 +02:00
codec - > patch_ops . init ( codec ) ;
2008-08-26 14:03:29 +02:00
2012-11-08 10:23:18 +01:00
if ( spec - > codec_variant = = ALC269_TYPE_ALC269VB )
alc269vb_toggle_power_output ( codec , 1 ) ;
if ( spec - > codec_variant = = ALC269_TYPE_ALC269VB & &
2012-05-25 08:08:38 +02:00
( alc_get_coef0 ( codec ) & 0x00ff ) = = 0x017 ) {
2011-07-07 18:23:21 +02:00
msleep ( 200 ) ;
}
2008-08-26 14:03:29 +02:00
2011-07-07 18:23:21 +02:00
snd_hda_codec_resume_amp ( codec ) ;
snd_hda_codec_resume_cache ( codec ) ;
hda_call_check_power_status ( codec , 0x01 ) ;
return 0 ;
}
2011-07-26 09:52:50 +02:00
# endif /* CONFIG_PM */
2008-08-26 14:03:29 +02:00
2012-07-20 10:37:25 +02:00
static void alc269_fixup_pincfg_no_hp_to_lineout ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-07-20 10:37:25 +02:00
{
struct alc_spec * spec = codec - > spec ;
2013-01-10 09:52:52 +01:00
if ( action = = HDA_FIXUP_ACT_PRE_PROBE )
2012-07-20 10:37:25 +02:00
spec - > parse_flags = HDA_PINCFG_NO_HP_FIXUP ;
}
2011-07-07 18:23:21 +02:00
static void alc269_fixup_hweq ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2011-07-07 18:23:21 +02:00
{
int coef ;
2008-08-26 14:03:29 +02:00
2013-01-10 09:52:52 +01:00
if ( action ! = HDA_FIXUP_ACT_INIT )
2011-07-07 18:23:21 +02:00
return ;
coef = alc_read_coef_idx ( codec , 0x1e ) ;
alc_write_coef_idx ( codec , 0x1e , coef | 0x80 ) ;
}
2008-08-26 14:03:29 +02:00
2011-07-07 18:23:21 +02:00
static void alc271_fixup_dmic ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2011-07-07 18:23:21 +02:00
{
static const struct hda_verb verbs [ ] = {
{ 0x20 , AC_VERB_SET_COEF_INDEX , 0x0d } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x4000 } ,
{ }
} ;
unsigned int cfg ;
2008-08-26 14:03:29 +02:00
2011-07-07 18:23:21 +02:00
if ( strcmp ( codec - > chip_name , " ALC271X " ) )
return ;
cfg = snd_hda_codec_get_pincfg ( codec , 0x12 ) ;
if ( get_defcfg_connect ( cfg ) = = AC_JACK_PORT_FIXED )
snd_hda_sequence_write ( codec , verbs ) ;
}
2008-08-26 14:03:29 +02:00
2011-07-09 14:42:25 +02:00
static void alc269_fixup_pcm_44k ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2011-07-09 14:42:25 +02:00
{
struct alc_spec * spec = codec - > spec ;
2013-01-10 09:52:52 +01:00
if ( action ! = HDA_FIXUP_ACT_PROBE )
2011-07-09 14:42:25 +02:00
return ;
/* Due to a hardware problem on Lenovo Ideadpad, we need to
* fix the sample rate of analog I / O to 44.1 kHz
*/
2012-12-19 15:22:24 +01:00
spec - > gen . stream_analog_playback = & alc269_44k_pcm_analog_playback ;
spec - > gen . stream_analog_capture = & alc269_44k_pcm_analog_capture ;
2011-07-09 14:42:25 +02:00
}
2011-08-03 07:48:37 +02:00
static void alc269_fixup_stereo_dmic ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2011-08-03 07:48:37 +02:00
{
int coef ;
2013-01-10 09:52:52 +01:00
if ( action ! = HDA_FIXUP_ACT_INIT )
2011-08-03 07:48:37 +02:00
return ;
/* The digital-mic unit sends PDM (differential signal) instead of
* the standard PCM , thus you can ' t record a valid mono stream as is .
* Below is a workaround specific to ALC269 to control the dmic
* signal source as mono .
*/
coef = alc_read_coef_idx ( codec , 0x07 ) ;
alc_write_coef_idx ( codec , 0x07 , coef | 0x80 ) ;
}
2011-08-16 15:08:49 +02:00
static void alc269_quanta_automute ( struct hda_codec * codec )
{
2012-12-19 15:22:24 +01:00
snd_hda_gen_update_outputs ( codec ) ;
2011-08-16 15:08:49 +02:00
snd_hda_codec_write ( codec , 0x20 , 0 ,
AC_VERB_SET_COEF_INDEX , 0x0c ) ;
snd_hda_codec_write ( codec , 0x20 , 0 ,
AC_VERB_SET_PROC_COEF , 0x680 ) ;
snd_hda_codec_write ( codec , 0x20 , 0 ,
AC_VERB_SET_COEF_INDEX , 0x0c ) ;
snd_hda_codec_write ( codec , 0x20 , 0 ,
AC_VERB_SET_PROC_COEF , 0x480 ) ;
}
static void alc269_fixup_quanta_mute ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2011-08-16 15:08:49 +02:00
{
struct alc_spec * spec = codec - > spec ;
2013-01-10 09:52:52 +01:00
if ( action ! = HDA_FIXUP_ACT_PROBE )
2011-08-16 15:08:49 +02:00
return ;
2012-12-19 15:22:24 +01:00
spec - > gen . automute_hook = alc269_quanta_automute ;
2011-08-16 15:08:49 +02:00
}
2013-01-10 17:33:58 +01:00
/* update mute-LED according to the speaker mute state via mic VREF pin */
static void alc269_fixup_mic_mute_hook ( void * private_data , int enabled )
2013-01-07 12:03:47 +01:00
{
struct hda_codec * codec = private_data ;
2013-01-10 17:33:58 +01:00
struct alc_spec * spec = codec - > spec ;
unsigned int pinval ;
if ( spec - > mute_led_polarity )
enabled = ! enabled ;
pinval = AC_PINCTL_IN_EN |
( enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80 ) ;
if ( spec - > mute_led_nid )
snd_hda_set_pin_ctl_cache ( codec , spec - > mute_led_nid , pinval ) ;
2013-01-07 12:03:47 +01:00
}
2013-01-10 17:33:58 +01:00
static void alc269_fixup_hp_mute_led ( struct hda_codec * codec ,
const struct hda_fixup * fix , int action )
2013-01-07 12:03:47 +01:00
{
struct alc_spec * spec = codec - > spec ;
2013-01-10 17:33:58 +01:00
const struct dmi_device * dev = NULL ;
if ( action ! = HDA_FIXUP_ACT_PRE_PROBE )
return ;
while ( ( dev = dmi_find_device ( DMI_DEV_TYPE_OEM_STRING , NULL , dev ) ) ) {
int pol , pin ;
if ( sscanf ( dev - > name , " HP_Mute_LED_%d_%x " , & pol , & pin ) ! = 2 )
continue ;
if ( pin < 0x0a | | pin > = 0x10 )
break ;
spec - > mute_led_polarity = pol ;
spec - > mute_led_nid = pin - 0x0a + 0x18 ;
spec - > gen . vmaster_mute . hook = alc269_fixup_mic_mute_hook ;
2012-12-20 14:57:18 +01:00
spec - > gen . vmaster_mute_enum = 1 ;
2013-01-10 17:33:58 +01:00
snd_printd ( " Detected mute LED for %x:%d \n " , spec - > mute_led_nid ,
spec - > mute_led_polarity ) ;
2013-01-07 12:03:47 +01:00
break ;
}
}
2013-02-18 11:41:55 +01:00
static void alc269_fixup_hp_mute_led_mic1 ( struct hda_codec * codec ,
const struct hda_fixup * fix , int action )
{
struct alc_spec * spec = codec - > spec ;
if ( action = = HDA_FIXUP_ACT_PRE_PROBE ) {
spec - > mute_led_polarity = 0 ;
spec - > mute_led_nid = 0x18 ;
spec - > gen . vmaster_mute . hook = alc269_fixup_mic_mute_hook ;
spec - > gen . vmaster_mute_enum = 1 ;
}
}
2013-01-10 17:33:58 +01:00
static void alc269_fixup_hp_mute_led_mic2 ( struct hda_codec * codec ,
const struct hda_fixup * fix , int action )
2012-03-12 12:35:27 +01:00
{
struct alc_spec * spec = codec - > spec ;
2013-01-10 17:14:29 +01:00
if ( action = = HDA_FIXUP_ACT_PRE_PROBE ) {
2013-01-10 17:33:58 +01:00
spec - > mute_led_polarity = 0 ;
spec - > mute_led_nid = 0x19 ;
spec - > gen . vmaster_mute . hook = alc269_fixup_mic_mute_hook ;
2012-12-20 14:57:18 +01:00
spec - > gen . vmaster_mute_enum = 1 ;
2012-03-12 12:35:27 +01:00
}
}
2013-03-18 14:15:58 +01:00
/* turn on/off mute LED per vmaster hook */
static void alc269_fixup_hp_gpio_mute_hook ( void * private_data , int enabled )
{
struct hda_codec * codec = private_data ;
struct alc_spec * spec = codec - > spec ;
unsigned int oldval = spec - > gpio_led ;
if ( enabled )
spec - > gpio_led & = ~ 0x08 ;
else
spec - > gpio_led | = 0x08 ;
if ( spec - > gpio_led ! = oldval )
snd_hda_codec_write ( codec , 0x01 , 0 , AC_VERB_SET_GPIO_DATA ,
spec - > gpio_led ) ;
}
/* turn on/off mic-mute LED per capture hook */
static void alc269_fixup_hp_gpio_mic_mute_hook ( struct hda_codec * codec ,
struct snd_ctl_elem_value * ucontrol )
{
struct alc_spec * spec = codec - > spec ;
unsigned int oldval = spec - > gpio_led ;
if ( ! ucontrol )
return ;
if ( ucontrol - > value . integer . value [ 0 ] | |
ucontrol - > value . integer . value [ 1 ] )
spec - > gpio_led & = ~ 0x10 ;
else
spec - > gpio_led | = 0x10 ;
if ( spec - > gpio_led ! = oldval )
snd_hda_codec_write ( codec , 0x01 , 0 , AC_VERB_SET_GPIO_DATA ,
spec - > gpio_led ) ;
}
static void alc269_fixup_hp_gpio_led ( struct hda_codec * codec ,
const struct hda_fixup * fix , int action )
{
struct alc_spec * spec = codec - > spec ;
static const struct hda_verb gpio_init [ ] = {
{ 0x01 , AC_VERB_SET_GPIO_MASK , 0x18 } ,
{ 0x01 , AC_VERB_SET_GPIO_DIRECTION , 0x18 } ,
{ }
} ;
if ( action = = HDA_FIXUP_ACT_PRE_PROBE ) {
spec - > gen . vmaster_mute . hook = alc269_fixup_hp_gpio_mute_hook ;
spec - > gen . cap_sync_hook = alc269_fixup_hp_gpio_mic_mute_hook ;
spec - > gpio_led = 0 ;
snd_hda_add_verbs ( codec , gpio_init ) ;
}
}
2012-11-18 22:56:40 -08:00
static void alc271_hp_gate_mic_jack ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix ,
2012-11-18 22:56:40 -08:00
int action )
{
struct alc_spec * spec = codec - > spec ;
2013-01-23 13:57:20 +01:00
if ( action = = HDA_FIXUP_ACT_PROBE ) {
if ( snd_BUG_ON ( ! spec - > gen . am_entry [ 1 ] . pin | |
! spec - > gen . autocfg . hp_pins [ 0 ] ) )
return ;
2012-12-19 15:22:24 +01:00
snd_hda_jack_set_gating_jack ( codec , spec - > gen . am_entry [ 1 ] . pin ,
spec - > gen . autocfg . hp_pins [ 0 ] ) ;
2013-01-23 13:57:20 +01:00
}
2012-11-18 22:56:40 -08:00
}
2012-06-22 19:12:10 +02:00
2011-07-07 18:23:21 +02:00
enum {
ALC269_FIXUP_SONY_VAIO ,
ALC275_FIXUP_SONY_VAIO_GPIO2 ,
ALC269_FIXUP_DELL_M101Z ,
ALC269_FIXUP_SKU_IGNORE ,
ALC269_FIXUP_ASUS_G73JW ,
ALC269_FIXUP_LENOVO_EAPD ,
ALC275_FIXUP_SONY_HWEQ ,
ALC271_FIXUP_DMIC ,
2011-07-09 14:42:25 +02:00
ALC269_FIXUP_PCM_44K ,
2011-08-03 07:48:37 +02:00
ALC269_FIXUP_STEREO_DMIC ,
2011-08-16 15:08:49 +02:00
ALC269_FIXUP_QUANTA_MUTE ,
ALC269_FIXUP_LIFEBOOK ,
2011-08-23 18:40:12 +02:00
ALC269_FIXUP_AMIC ,
ALC269_FIXUP_DMIC ,
ALC269VB_FIXUP_AMIC ,
ALC269VB_FIXUP_DMIC ,
2013-01-10 17:33:58 +01:00
ALC269_FIXUP_HP_MUTE_LED ,
2013-02-18 11:41:55 +01:00
ALC269_FIXUP_HP_MUTE_LED_MIC1 ,
2013-01-10 17:33:58 +01:00
ALC269_FIXUP_HP_MUTE_LED_MIC2 ,
2013-03-18 14:15:58 +01:00
ALC269_FIXUP_HP_GPIO_LED ,
2012-06-22 19:12:10 +02:00
ALC269_FIXUP_INV_DMIC ,
2012-07-20 10:37:25 +02:00
ALC269_FIXUP_LENOVO_DOCK ,
ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT ,
2012-11-18 22:56:40 -08:00
ALC271_FIXUP_AMIC_MIC2 ,
ALC271_FIXUP_HP_GATE_MIC_JACK ,
2008-08-26 14:03:29 +02:00
} ;
2013-01-10 09:52:52 +01:00
static const struct hda_fixup alc269_fixups [ ] = {
2011-07-07 18:23:21 +02:00
[ ALC269_FIXUP_SONY_VAIO ] = {
2013-01-10 10:18:14 +01:00
. type = HDA_FIXUP_PINCTLS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
{ 0x19 , PIN_VREFGRD } ,
2011-07-07 18:23:21 +02:00
{ }
}
2008-08-26 14:03:29 +02:00
} ,
2011-07-07 18:23:21 +02:00
[ ALC275_FIXUP_SONY_VAIO_GPIO2 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-07-07 18:23:21 +02:00
. v . verbs = ( const struct hda_verb [ ] ) {
{ 0x01 , AC_VERB_SET_GPIO_MASK , 0x04 } ,
{ 0x01 , AC_VERB_SET_GPIO_DIRECTION , 0x04 } ,
{ 0x01 , AC_VERB_SET_GPIO_DATA , 0x00 } ,
{ }
} ,
. chained = true ,
. chain_id = ALC269_FIXUP_SONY_VAIO
} ,
[ ALC269_FIXUP_DELL_M101Z ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-07-07 18:23:21 +02:00
. v . verbs = ( const struct hda_verb [ ] ) {
/* Enables internal speaker */
{ 0x20 , AC_VERB_SET_COEF_INDEX , 13 } ,
{ 0x20 , AC_VERB_SET_PROC_COEF , 0x4040 } ,
{ }
}
} ,
[ ALC269_FIXUP_SKU_IGNORE ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-05-07 17:17:32 +02:00
. v . func = alc_fixup_sku_ignore ,
2011-07-07 18:23:21 +02:00
} ,
[ ALC269_FIXUP_ASUS_G73JW ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-07-07 18:23:21 +02:00
{ 0x17 , 0x99130111 } , /* subwoofer */
{ }
}
} ,
[ ALC269_FIXUP_LENOVO_EAPD ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-07-07 18:23:21 +02:00
. v . verbs = ( const struct hda_verb [ ] ) {
{ 0x14 , AC_VERB_SET_EAPD_BTLENABLE , 0 } ,
{ }
}
} ,
[ ALC275_FIXUP_SONY_HWEQ ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2011-07-07 18:23:21 +02:00
. v . func = alc269_fixup_hweq ,
. chained = true ,
. chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
} ,
[ ALC271_FIXUP_DMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2011-07-07 18:23:21 +02:00
. v . func = alc271_fixup_dmic ,
2008-08-26 14:03:29 +02:00
} ,
2011-07-09 14:42:25 +02:00
[ ALC269_FIXUP_PCM_44K ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2011-07-09 14:42:25 +02:00
. v . func = alc269_fixup_pcm_44k ,
2012-08-08 08:43:37 +02:00
. chained = true ,
. chain_id = ALC269_FIXUP_QUANTA_MUTE
2011-07-09 14:42:25 +02:00
} ,
2011-08-03 07:48:37 +02:00
[ ALC269_FIXUP_STEREO_DMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2011-08-03 07:48:37 +02:00
. v . func = alc269_fixup_stereo_dmic ,
} ,
2011-08-16 15:08:49 +02:00
[ ALC269_FIXUP_QUANTA_MUTE ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2011-08-16 15:08:49 +02:00
. v . func = alc269_fixup_quanta_mute ,
} ,
[ ALC269_FIXUP_LIFEBOOK ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-16 15:08:49 +02:00
{ 0x1a , 0x2101103f } , /* dock line-out */
{ 0x1b , 0x23a11040 } , /* dock mic-in */
{ }
} ,
. chained = true ,
. chain_id = ALC269_FIXUP_QUANTA_MUTE
} ,
2011-08-23 18:40:12 +02:00
[ ALC269_FIXUP_AMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:40:12 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x15 , 0x0121401f } , /* HP out */
{ 0x18 , 0x01a19c20 } , /* mic */
{ 0x19 , 0x99a3092f } , /* int-mic */
{ }
} ,
} ,
[ ALC269_FIXUP_DMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:40:12 +02:00
{ 0x12 , 0x99a3092f } , /* int-mic */
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x15 , 0x0121401f } , /* HP out */
{ 0x18 , 0x01a19c20 } , /* mic */
{ }
} ,
} ,
[ ALC269VB_FIXUP_AMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:40:12 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x18 , 0x01a19c20 } , /* mic */
{ 0x19 , 0x99a3092f } , /* int-mic */
{ 0x21 , 0x0121401f } , /* HP out */
{ }
} ,
} ,
2012-01-03 08:45:56 +01:00
[ ALC269VB_FIXUP_DMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:40:12 +02:00
{ 0x12 , 0x99a3092f } , /* int-mic */
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x18 , 0x01a19c20 } , /* mic */
{ 0x21 , 0x0121401f } , /* HP out */
{ }
} ,
} ,
2013-01-10 17:33:58 +01:00
[ ALC269_FIXUP_HP_MUTE_LED ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2013-01-10 17:33:58 +01:00
. v . func = alc269_fixup_hp_mute_led ,
2013-01-07 12:03:47 +01:00
} ,
2013-02-18 11:41:55 +01:00
[ ALC269_FIXUP_HP_MUTE_LED_MIC1 ] = {
. type = HDA_FIXUP_FUNC ,
. v . func = alc269_fixup_hp_mute_led_mic1 ,
} ,
2013-01-10 17:33:58 +01:00
[ ALC269_FIXUP_HP_MUTE_LED_MIC2 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2013-01-10 17:33:58 +01:00
. v . func = alc269_fixup_hp_mute_led_mic2 ,
2012-03-12 12:35:27 +01:00
} ,
2013-03-18 14:15:58 +01:00
[ ALC269_FIXUP_HP_GPIO_LED ] = {
. type = HDA_FIXUP_FUNC ,
. v . func = alc269_fixup_hp_gpio_led ,
} ,
2012-06-22 19:12:10 +02:00
[ ALC269_FIXUP_INV_DMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
. v . func = alc_fixup_inv_dmic_0x12 ,
2012-06-22 19:12:10 +02:00
} ,
2012-07-20 10:37:25 +02:00
[ ALC269_FIXUP_LENOVO_DOCK ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-07-20 10:37:25 +02:00
{ 0x19 , 0x23a11040 } , /* dock mic */
{ 0x1b , 0x2121103f } , /* dock headphone */
{ }
} ,
. chained = true ,
. chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT
} ,
[ ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-07-20 10:37:25 +02:00
. v . func = alc269_fixup_pincfg_no_hp_to_lineout ,
} ,
2012-11-18 22:56:40 -08:00
[ ALC271_FIXUP_AMIC_MIC2 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-11-18 22:56:40 -08:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x19 , 0x01a19c20 } , /* mic */
{ 0x1b , 0x99a7012f } , /* int-mic */
{ 0x21 , 0x0121401f } , /* HP out */
{ }
} ,
} ,
[ ALC271_FIXUP_HP_GATE_MIC_JACK ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-11-18 22:56:40 -08:00
. v . func = alc271_hp_gate_mic_jack ,
. chained = true ,
. chain_id = ALC271_FIXUP_AMIC_MIC2 ,
} ,
2008-08-26 14:03:29 +02:00
} ;
2011-07-07 18:23:21 +02:00
static const struct snd_pci_quirk alc269_fixup_tbl [ ] = {
2012-06-22 19:12:10 +02:00
SND_PCI_QUIRK ( 0x1025 , 0x029b , " Acer 1810TZ " , ALC269_FIXUP_INV_DMIC ) ,
SND_PCI_QUIRK ( 0x1025 , 0x0349 , " Acer AOD260 " , ALC269_FIXUP_INV_DMIC ) ,
2013-01-10 17:33:58 +01:00
SND_PCI_QUIRK ( 0x103c , 0x1586 , " HP " , ALC269_FIXUP_HP_MUTE_LED_MIC2 ) ,
2013-03-18 14:15:58 +01:00
SND_PCI_QUIRK ( 0x103c , 0x18e6 , " HP " , ALC269_FIXUP_HP_GPIO_LED ) ,
2013-02-18 11:41:55 +01:00
SND_PCI_QUIRK ( 0x103c , 0x1973 , " HP Pavilion " , ALC269_FIXUP_HP_MUTE_LED_MIC1 ) ,
SND_PCI_QUIRK ( 0x103c , 0x1983 , " HP Pavilion " , ALC269_FIXUP_HP_MUTE_LED_MIC1 ) ,
2013-01-10 17:33:58 +01:00
SND_PCI_QUIRK_VENDOR ( 0x103c , " HP " , ALC269_FIXUP_HP_MUTE_LED ) ,
2012-04-20 10:01:46 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x1427 , " Asus Zenbook UX31E " , ALC269VB_FIXUP_DMIC ) ,
2012-09-21 17:44:58 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x1517 , " Asus Zenbook UX31A " , ALC269VB_FIXUP_DMIC ) ,
2011-07-09 14:42:25 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x1a13 , " Asus G73Jw " , ALC269_FIXUP_ASUS_G73JW ) ,
2012-06-22 19:12:10 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x1b13 , " Asus U41SV " , ALC269_FIXUP_INV_DMIC ) ,
2011-08-03 07:48:37 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x16e3 , " ASUS UX50 " , ALC269_FIXUP_STEREO_DMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x831a , " ASUS P901 " , ALC269_FIXUP_STEREO_DMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x834a , " ASUS S101 " , ALC269_FIXUP_STEREO_DMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x8398 , " ASUS P1005 " , ALC269_FIXUP_STEREO_DMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x83ce , " ASUS P1005 " , ALC269_FIXUP_STEREO_DMIC ) ,
2011-07-07 18:23:21 +02:00
SND_PCI_QUIRK ( 0x104d , 0x9073 , " Sony VAIO " , ALC275_FIXUP_SONY_VAIO_GPIO2 ) ,
SND_PCI_QUIRK ( 0x104d , 0x907b , " Sony VAIO " , ALC275_FIXUP_SONY_HWEQ ) ,
SND_PCI_QUIRK ( 0x104d , 0x9084 , " Sony VAIO " , ALC275_FIXUP_SONY_HWEQ ) ,
SND_PCI_QUIRK_VENDOR ( 0x104d , " Sony VAIO " , ALC269_FIXUP_SONY_VAIO ) ,
SND_PCI_QUIRK ( 0x1028 , 0x0470 , " Dell M101z " , ALC269_FIXUP_DELL_M101Z ) ,
2013-01-19 12:17:54 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x0740 , " Acer AO725 " , ALC271_FIXUP_HP_GATE_MIC_JACK ) ,
2012-11-18 22:56:40 -08:00
SND_PCI_QUIRK ( 0x1025 , 0x0742 , " Acer AO756 " , ALC271_FIXUP_HP_GATE_MIC_JACK ) ,
2011-07-07 18:23:21 +02:00
SND_PCI_QUIRK_VENDOR ( 0x1025 , " Acer Aspire " , ALC271_FIXUP_DMIC ) ,
2011-08-16 15:08:49 +02:00
SND_PCI_QUIRK ( 0x10cf , 0x1475 , " Lifebook " , ALC269_FIXUP_LIFEBOOK ) ,
2011-07-07 18:23:21 +02:00
SND_PCI_QUIRK ( 0x17aa , 0x20f2 , " Thinkpad SL410/510 " , ALC269_FIXUP_SKU_IGNORE ) ,
SND_PCI_QUIRK ( 0x17aa , 0x215e , " Thinkpad L512 " , ALC269_FIXUP_SKU_IGNORE ) ,
SND_PCI_QUIRK ( 0x17aa , 0x21b8 , " Thinkpad Edge 14 " , ALC269_FIXUP_SKU_IGNORE ) ,
SND_PCI_QUIRK ( 0x17aa , 0x21ca , " Thinkpad L412 " , ALC269_FIXUP_SKU_IGNORE ) ,
SND_PCI_QUIRK ( 0x17aa , 0x21e9 , " Thinkpad Edge 15 " , ALC269_FIXUP_SKU_IGNORE ) ,
2012-08-02 09:04:39 +02:00
SND_PCI_QUIRK ( 0x17aa , 0x21f6 , " Thinkpad T530 " , ALC269_FIXUP_LENOVO_DOCK ) ,
2012-08-06 23:02:01 +02:00
SND_PCI_QUIRK ( 0x17aa , 0x21fa , " Thinkpad X230 " , ALC269_FIXUP_LENOVO_DOCK ) ,
2012-10-19 22:46:00 +02:00
SND_PCI_QUIRK ( 0x17aa , 0x21f3 , " Thinkpad T430 " , ALC269_FIXUP_LENOVO_DOCK ) ,
2012-08-06 13:14:18 +02:00
SND_PCI_QUIRK ( 0x17aa , 0x21fb , " Thinkpad T430s " , ALC269_FIXUP_LENOVO_DOCK ) ,
2012-07-20 10:37:25 +02:00
SND_PCI_QUIRK ( 0x17aa , 0x2203 , " Thinkpad X230 Tablet " , ALC269_FIXUP_LENOVO_DOCK ) ,
2012-08-08 08:43:37 +02:00
SND_PCI_QUIRK ( 0x17aa , 0x3bf8 , " Quanta FL1 " , ALC269_FIXUP_PCM_44K ) ,
2011-07-07 18:23:21 +02:00
SND_PCI_QUIRK ( 0x17aa , 0x9e54 , " LENOVO NB " , ALC269_FIXUP_LENOVO_EAPD ) ,
2011-08-23 18:40:12 +02:00
2012-02-16 13:03:18 +01:00
#if 0
2011-08-23 18:40:12 +02:00
/* Below is a quirk table taken from the old code.
* Basically the device should work as is without the fixup table .
* If BIOS doesn ' t give a proper info , enable the corresponding
* fixup entry .
2012-04-12 22:11:25 +02:00
*/
2011-08-23 18:40:12 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x8330 , " ASUS Eeepc P703 P900A " ,
ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1013 , " ASUS N61Da " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1143 , " ASUS B53f " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1133 , " ASUS UJ20ft " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1183 , " ASUS K72DR " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x11b3 , " ASUS K52DR " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x11e3 , " ASUS U33Jc " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1273 , " ASUS UL80Jt " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1283 , " ASUS U53Jc " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x12b3 , " ASUS N82JV " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x12d3 , " ASUS N61Jv " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x13a3 , " ASUS UL30Vt " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1373 , " ASUS G73JX " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1383 , " ASUS UJ30Jc " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x13d3 , " ASUS N61JA " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1413 , " ASUS UL50 " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1443 , " ASUS UL30 " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1453 , " ASUS M60Jv " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1483 , " ASUS UL80 " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x14f3 , " ASUS F83Vf " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x14e3 , " ASUS UL20 " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1513 , " ASUS UX30 " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1593 , " ASUS N51Vn " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x15a3 , " ASUS N60Jv " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x15b3 , " ASUS N60Dp " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x15c3 , " ASUS N70De " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x15e3 , " ASUS F83T " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1643 , " ASUS M60J " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1653 , " ASUS U50 " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1693 , " ASUS F50N " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x16a3 , " ASUS F5Q " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1723 , " ASUS P80 " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1743 , " ASUS U80 " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1773 , " ASUS U20A " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1883 , " ASUS F81Se " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x152d , 0x1778 , " Quanta ON1 " , ALC269_FIXUP_DMIC ) ,
SND_PCI_QUIRK ( 0x17aa , 0x3be9 , " Quanta Wistron " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x17aa , 0x3bf8 , " Quanta FL1 " , ALC269_FIXUP_AMIC ) ,
SND_PCI_QUIRK ( 0x17ff , 0x059a , " Quanta EL3 " , ALC269_FIXUP_DMIC ) ,
SND_PCI_QUIRK ( 0x17ff , 0x059b , " Quanta JR1 " , ALC269_FIXUP_DMIC ) ,
# endif
{ }
} ;
2013-01-10 09:52:52 +01:00
static const struct hda_model_fixup alc269_fixup_models [ ] = {
2011-08-23 18:40:12 +02:00
{ . id = ALC269_FIXUP_AMIC , . name = " laptop-amic " } ,
{ . id = ALC269_FIXUP_DMIC , . name = " laptop-dmic " } ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
{ . id = ALC269_FIXUP_STEREO_DMIC , . name = " alc269-dmic " } ,
{ . id = ALC271_FIXUP_DMIC , . name = " alc271-dmic " } ,
{ . id = ALC269_FIXUP_INV_DMIC , . name = " inv-dmic " } ,
2012-07-20 10:37:25 +02:00
{ . id = ALC269_FIXUP_LENOVO_DOCK , . name = " lenovo-dock " } ,
2013-03-18 14:15:58 +01:00
{ . id = ALC269_FIXUP_HP_GPIO_LED , . name = " hp-gpio-led " } ,
2011-07-07 18:23:21 +02:00
{ }
2008-05-27 12:05:31 +02:00
} ;
2012-03-07 08:37:19 +01:00
static void alc269_fill_coef ( struct hda_codec * codec )
2011-07-07 18:23:21 +02:00
{
2012-03-07 08:25:20 +01:00
struct alc_spec * spec = codec - > spec ;
2011-07-07 18:23:21 +02:00
int val ;
2009-12-17 12:23:00 +01:00
2012-03-07 08:25:20 +01:00
if ( spec - > codec_variant ! = ALC269_TYPE_ALC269VB )
2012-03-07 08:37:19 +01:00
return ;
2012-03-07 08:25:20 +01:00
2011-10-17 16:50:59 +02:00
if ( ( alc_get_coef0 ( codec ) & 0x00ff ) < 0x015 ) {
2011-07-07 18:23:21 +02:00
alc_write_coef_idx ( codec , 0xf , 0x960b ) ;
alc_write_coef_idx ( codec , 0xe , 0x8817 ) ;
}
2009-12-17 12:23:00 +01:00
2011-10-17 16:50:59 +02:00
if ( ( alc_get_coef0 ( codec ) & 0x00ff ) = = 0x016 ) {
2011-07-07 18:23:21 +02:00
alc_write_coef_idx ( codec , 0xf , 0x960b ) ;
alc_write_coef_idx ( codec , 0xe , 0x8814 ) ;
}
2009-12-17 12:23:00 +01:00
2011-10-17 16:50:59 +02:00
if ( ( alc_get_coef0 ( codec ) & 0x00ff ) = = 0x017 ) {
2011-07-07 18:23:21 +02:00
val = alc_read_coef_idx ( codec , 0x04 ) ;
/* Power up output pin */
alc_write_coef_idx ( codec , 0x04 , val | ( 1 < < 11 ) ) ;
}
2009-12-17 12:23:00 +01:00
2011-10-17 16:50:59 +02:00
if ( ( alc_get_coef0 ( codec ) & 0x00ff ) = = 0x018 ) {
2011-07-07 18:23:21 +02:00
val = alc_read_coef_idx ( codec , 0xd ) ;
if ( ( val & 0x0c00 ) > > 10 ! = 0x1 ) {
/* Capless ramp up clock control */
alc_write_coef_idx ( codec , 0xd , val | ( 1 < < 10 ) ) ;
}
val = alc_read_coef_idx ( codec , 0x17 ) ;
if ( ( val & 0x01c0 ) > > 6 ! = 0x4 ) {
/* Class D power on reset */
alc_write_coef_idx ( codec , 0x17 , val | ( 1 < < 7 ) ) ;
}
}
2009-12-17 12:23:00 +01:00
2011-07-07 18:23:21 +02:00
val = alc_read_coef_idx ( codec , 0xd ) ; /* Class D */
alc_write_coef_idx ( codec , 0xd , val | ( 1 < < 14 ) ) ;
2007-04-12 13:06:07 +02:00
2011-07-07 18:23:21 +02:00
val = alc_read_coef_idx ( codec , 0x4 ) ; /* HP */
alc_write_coef_idx ( codec , 0x4 , val | ( 1 < < 11 ) ) ;
}
2011-04-07 10:24:23 +02:00
2011-07-07 18:23:21 +02:00
/*
*/
static int patch_alc269 ( struct hda_codec * codec )
{
struct alc_spec * spec ;
2012-05-07 18:03:15 +02:00
int err ;
2008-08-26 14:03:29 +02:00
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0x0b ) ;
2011-10-17 16:39:09 +02:00
if ( err < 0 )
2012-05-07 18:03:15 +02:00
return err ;
spec = codec - > spec ;
2012-12-19 15:22:24 +01:00
spec - > gen . shared_mic_vref_pin = 0x18 ;
2011-10-17 16:39:09 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_pick_fixup ( codec , alc269_fixup_models ,
2012-09-27 10:38:14 -03:00
alc269_fixup_tbl , alc269_fixups ) ;
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PRE_PROBE ) ;
2012-09-27 10:38:14 -03:00
alc_auto_parse_customize_define ( codec ) ;
2013-03-18 11:25:51 +01:00
if ( has_cdefine_beep ( codec ) )
spec - > gen . beep_nid = 0x01 ;
2013-01-10 10:25:48 +01:00
switch ( codec - > vendor_id ) {
case 0x10ec0269 :
2011-07-07 18:23:21 +02:00
spec - > codec_variant = ALC269_TYPE_ALC269VA ;
2011-10-17 16:50:59 +02:00
switch ( alc_get_coef0 ( codec ) & 0x00f0 ) {
case 0x0010 :
2011-07-07 18:23:21 +02:00
if ( codec - > bus - > pci - > subsystem_vendor = = 0x1025 & &
2011-10-17 16:39:09 +02:00
spec - > cdefine . platform_type = = 1 )
2011-10-17 16:00:35 +02:00
err = alc_codec_rename ( codec , " ALC271X " ) ;
2011-07-07 18:23:21 +02:00
spec - > codec_variant = ALC269_TYPE_ALC269VB ;
2011-10-17 16:50:59 +02:00
break ;
case 0x0020 :
2011-10-17 16:39:09 +02:00
if ( codec - > bus - > pci - > subsystem_vendor = = 0x17aa & &
codec - > bus - > pci - > subsystem_device = = 0x21f3 )
2011-10-17 16:00:35 +02:00
err = alc_codec_rename ( codec , " ALC3202 " ) ;
2011-07-07 18:23:21 +02:00
spec - > codec_variant = ALC269_TYPE_ALC269VC ;
2011-10-17 16:50:59 +02:00
break ;
2012-05-25 08:08:38 +02:00
case 0x0030 :
spec - > codec_variant = ALC269_TYPE_ALC269VD ;
break ;
2011-10-17 16:50:59 +02:00
default :
2011-07-07 18:23:21 +02:00
alc_fix_pll_init ( codec , 0x20 , 0x04 , 15 ) ;
2011-10-17 16:50:59 +02:00
}
2011-10-17 16:39:09 +02:00
if ( err < 0 )
goto error ;
2012-03-07 08:37:19 +01:00
spec - > init_hook = alc269_fill_coef ;
2011-07-07 18:23:21 +02:00
alc269_fill_coef ( codec ) ;
2013-01-10 10:25:48 +01:00
break ;
case 0x10ec0280 :
case 0x10ec0290 :
spec - > codec_variant = ALC269_TYPE_ALC280 ;
break ;
2013-03-07 09:19:38 +01:00
case 0x10ec0233 :
2013-01-10 10:25:48 +01:00
case 0x10ec0282 :
case 0x10ec0283 :
spec - > codec_variant = ALC269_TYPE_ALC282 ;
break ;
case 0x10ec0284 :
case 0x10ec0292 :
spec - > codec_variant = ALC269_TYPE_ALC284 ;
break ;
2011-07-07 18:23:21 +02:00
}
2008-05-27 12:05:31 +02:00
2011-08-23 18:40:12 +02:00
/* automatic parse from the BIOS config */
err = alc269_parse_auto_config ( codec ) ;
2011-10-17 16:39:09 +02:00
if ( err < 0 )
goto error ;
2008-05-27 12:05:31 +02:00
2013-03-18 11:25:51 +01:00
if ( ! spec - > gen . no_analog & & spec - > gen . beep_nid )
2011-07-07 18:23:21 +02:00
set_beep_amp ( spec , 0x0b , 0x04 , HDA_INPUT ) ;
2008-08-26 14:03:29 +02:00
2011-07-07 18:23:21 +02:00
codec - > patch_ops = alc_patch_ops ;
2011-07-26 09:52:50 +02:00
# ifdef CONFIG_PM
2011-07-07 18:23:21 +02:00
codec - > patch_ops . resume = alc269_resume ;
# endif
spec - > shutup = alc269_shutup ;
2009-12-17 12:23:00 +01:00
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PROBE ) ;
2012-02-20 15:47:55 +01:00
2011-07-07 18:23:21 +02:00
return 0 ;
2011-10-17 16:39:09 +02:00
error :
alc_free ( codec ) ;
return err ;
2011-07-07 18:23:21 +02:00
}
2008-08-26 14:03:29 +02:00
2011-07-07 18:23:21 +02:00
/*
* ALC861
*/
2009-04-21 07:39:04 +02:00
2011-07-07 18:23:21 +02:00
static int alc861_parse_auto_config ( struct hda_codec * codec )
2008-05-27 12:05:31 +02:00
{
2011-07-07 18:23:21 +02:00
static const hda_nid_t alc861_ignore [ ] = { 0x1d , 0 } ;
2011-07-08 16:55:13 +02:00
static const hda_nid_t alc861_ssids [ ] = { 0x0e , 0x0f , 0x0b , 0 } ;
return alc_parse_auto_config ( codec , alc861_ignore , alc861_ssids ) ;
2011-04-27 15:14:23 +02:00
}
2011-07-07 18:23:21 +02:00
/* Pin config fixes */
enum {
2012-02-13 11:56:25 +01:00
ALC861_FIXUP_FSC_AMILO_PI1505 ,
ALC861_FIXUP_AMP_VREF_0F ,
ALC861_FIXUP_NO_JACK_DETECT ,
ALC861_FIXUP_ASUS_A6RP ,
2011-07-07 18:23:21 +02:00
} ;
2009-10-02 09:03:58 +02:00
2012-01-30 10:54:08 +01:00
/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
static void alc861_fixup_asus_amp_vref_0f ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-01-30 10:54:08 +01:00
{
struct alc_spec * spec = codec - > spec ;
unsigned int val ;
2013-01-10 09:52:52 +01:00
if ( action ! = HDA_FIXUP_ACT_INIT )
2012-01-30 10:54:08 +01:00
return ;
2013-01-10 10:12:22 +01:00
val = snd_hda_codec_get_pin_target ( codec , 0x0f ) ;
2012-01-30 10:54:08 +01:00
if ( ! ( val & ( AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN ) ) )
val | = AC_PINCTL_IN_EN ;
val | = AC_PINCTL_VREF_50 ;
2012-04-20 12:34:50 +02:00
snd_hda_set_pin_ctl ( codec , 0x0f , val ) ;
2012-12-19 15:22:24 +01:00
spec - > gen . keep_vref_in_automute = 1 ;
2012-01-30 10:54:08 +01:00
}
2012-02-13 11:56:25 +01:00
/* suppress the jack-detection */
static void alc_fixup_no_jack_detect ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2012-02-13 11:56:25 +01:00
{
2013-01-10 09:52:52 +01:00
if ( action = = HDA_FIXUP_ACT_PRE_PROBE )
2012-02-13 11:56:25 +01:00
codec - > no_jack_detect = 1 ;
2012-04-12 22:11:25 +02:00
}
2012-02-13 11:56:25 +01:00
2013-01-10 09:52:52 +01:00
static const struct hda_fixup alc861_fixups [ ] = {
2012-02-13 11:56:25 +01:00
[ ALC861_FIXUP_FSC_AMILO_PI1505 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-07-07 18:23:21 +02:00
{ 0x0b , 0x0221101f } , /* HP */
{ 0x0f , 0x90170310 } , /* speaker */
{ }
}
} ,
2012-02-13 11:56:25 +01:00
[ ALC861_FIXUP_AMP_VREF_0F ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-01-30 10:54:08 +01:00
. v . func = alc861_fixup_asus_amp_vref_0f ,
2012-01-25 09:55:46 +01:00
} ,
2012-02-13 11:56:25 +01:00
[ ALC861_FIXUP_NO_JACK_DETECT ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-02-13 11:56:25 +01:00
. v . func = alc_fixup_no_jack_detect ,
} ,
[ ALC861_FIXUP_ASUS_A6RP ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-02-13 11:56:25 +01:00
. v . func = alc861_fixup_asus_amp_vref_0f ,
. chained = true ,
. chain_id = ALC861_FIXUP_NO_JACK_DETECT ,
}
2011-07-07 18:23:21 +02:00
} ;
2009-10-02 09:03:58 +02:00
2011-07-07 18:23:21 +02:00
static const struct snd_pci_quirk alc861_fixup_tbl [ ] = {
2012-02-13 11:56:25 +01:00
SND_PCI_QUIRK ( 0x1043 , 0x1393 , " ASUS A6Rp " , ALC861_FIXUP_ASUS_A6RP ) ,
SND_PCI_QUIRK_VENDOR ( 0x1043 , " ASUS laptop " , ALC861_FIXUP_AMP_VREF_0F ) ,
SND_PCI_QUIRK ( 0x1462 , 0x7254 , " HP DX2200 " , ALC861_FIXUP_NO_JACK_DETECT ) ,
SND_PCI_QUIRK ( 0x1584 , 0x2b01 , " Haier W18 " , ALC861_FIXUP_AMP_VREF_0F ) ,
SND_PCI_QUIRK ( 0x1584 , 0x0000 , " Uniwill ECS M31EI " , ALC861_FIXUP_AMP_VREF_0F ) ,
SND_PCI_QUIRK ( 0x1734 , 0x10c7 , " FSC Amilo Pi1505 " , ALC861_FIXUP_FSC_AMILO_PI1505 ) ,
2011-07-07 18:23:21 +02:00
{ }
} ;
2011-06-27 12:34:01 +02:00
2011-07-07 18:23:21 +02:00
/*
*/
static int patch_alc861 ( struct hda_codec * codec )
2009-10-02 09:03:58 +02:00
{
2011-07-07 18:23:21 +02:00
struct alc_spec * spec ;
int err ;
2009-10-02 09:03:58 +02:00
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0x15 ) ;
if ( err < 0 )
return err ;
2011-07-07 18:23:21 +02:00
2012-05-07 18:03:15 +02:00
spec = codec - > spec ;
2013-03-18 11:25:51 +01:00
spec - > gen . beep_nid = 0x23 ;
2011-07-07 18:23:21 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_pick_fixup ( codec , NULL , alc861_fixup_tbl , alc861_fixups ) ;
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PRE_PROBE ) ;
2011-06-27 12:34:01 +02:00
2011-08-23 17:34:25 +02:00
/* automatic parse from the BIOS config */
err = alc861_parse_auto_config ( codec ) ;
2011-10-17 16:39:09 +02:00
if ( err < 0 )
goto error ;
2011-06-27 12:34:01 +02:00
2013-03-18 11:25:51 +01:00
if ( ! spec - > gen . no_analog )
2011-07-08 16:55:13 +02:00
set_beep_amp ( spec , 0x23 , 0 , HDA_OUTPUT ) ;
2009-10-02 09:03:58 +02:00
2011-07-07 18:23:21 +02:00
codec - > patch_ops = alc_patch_ops ;
2012-08-24 18:38:08 +02:00
# ifdef CONFIG_PM
2011-08-23 17:34:25 +02:00
spec - > power_hook = alc_power_eapd ;
2011-07-07 18:23:21 +02:00
# endif
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PROBE ) ;
2012-02-20 15:47:55 +01:00
2011-07-07 18:23:21 +02:00
return 0 ;
2011-10-17 16:39:09 +02:00
error :
alc_free ( codec ) ;
return err ;
2009-10-02 09:03:58 +02:00
}
2011-07-07 18:23:21 +02:00
/*
* ALC861 - VD support
*
* Based on ALC882
*
* In addition , an independent DAC
*/
static int alc861vd_parse_auto_config ( struct hda_codec * codec )
2007-04-12 13:06:07 +02:00
{
2011-07-07 18:23:21 +02:00
static const hda_nid_t alc861vd_ignore [ ] = { 0x1d , 0 } ;
2011-07-08 16:55:13 +02:00
static const hda_nid_t alc861vd_ssids [ ] = { 0x15 , 0x1b , 0x14 , 0 } ;
return alc_parse_auto_config ( codec , alc861vd_ignore , alc861vd_ssids ) ;
2011-04-27 16:35:23 +02:00
}
2011-07-07 18:23:21 +02:00
enum {
2011-08-23 17:28:55 +02:00
ALC660VD_FIX_ASUS_GPIO1 ,
ALC861VD_FIX_DALLAS ,
2011-07-07 18:23:21 +02:00
} ;
2011-04-27 16:35:23 +02:00
2011-08-23 17:28:55 +02:00
/* exclude VREF80 */
static void alc861vd_fixup_dallas ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2011-08-23 17:28:55 +02:00
{
2013-01-10 09:52:52 +01:00
if ( action = = HDA_FIXUP_ACT_PRE_PROBE ) {
2012-12-17 20:06:49 +01:00
snd_hda_override_pin_caps ( codec , 0x18 , 0x00000734 ) ;
snd_hda_override_pin_caps ( codec , 0x19 , 0x0000073c ) ;
2011-08-23 17:28:55 +02:00
}
}
2013-01-10 09:52:52 +01:00
static const struct hda_fixup alc861vd_fixups [ ] = {
2011-07-07 18:23:21 +02:00
[ ALC660VD_FIX_ASUS_GPIO1 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-07-07 18:23:21 +02:00
. v . verbs = ( const struct hda_verb [ ] ) {
2011-08-23 17:28:55 +02:00
/* reset GPIO1 */
2011-07-07 18:23:21 +02:00
{ 0x01 , AC_VERB_SET_GPIO_MASK , 0x03 } ,
{ 0x01 , AC_VERB_SET_GPIO_DIRECTION , 0x01 } ,
{ 0x01 , AC_VERB_SET_GPIO_DATA , 0x01 } ,
{ }
}
} ,
2011-08-23 17:28:55 +02:00
[ ALC861VD_FIX_DALLAS ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2011-08-23 17:28:55 +02:00
. v . func = alc861vd_fixup_dallas ,
} ,
2011-07-07 18:23:21 +02:00
} ;
2011-04-27 16:35:23 +02:00
2011-07-07 18:23:21 +02:00
static const struct snd_pci_quirk alc861vd_fixup_tbl [ ] = {
2011-08-23 17:28:55 +02:00
SND_PCI_QUIRK ( 0x103c , 0x30bf , " HP TX1000 " , ALC861VD_FIX_DALLAS ) ,
2011-07-07 18:23:21 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x1339 , " ASUS A7-K " , ALC660VD_FIX_ASUS_GPIO1 ) ,
2011-08-23 17:28:55 +02:00
SND_PCI_QUIRK ( 0x1179 , 0xff31 , " Toshiba L30-149 " , ALC861VD_FIX_DALLAS ) ,
2011-07-07 18:23:21 +02:00
{ }
} ;
2011-04-27 16:35:23 +02:00
2011-07-07 18:23:21 +02:00
/*
*/
static int patch_alc861vd ( struct hda_codec * codec )
2011-04-27 16:35:23 +02:00
{
2011-07-07 18:23:21 +02:00
struct alc_spec * spec ;
2011-08-23 17:34:25 +02:00
int err ;
2011-04-27 16:35:23 +02:00
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0x0b ) ;
if ( err < 0 )
return err ;
2011-07-07 18:23:21 +02:00
2012-05-07 18:03:15 +02:00
spec = codec - > spec ;
2013-03-18 11:25:51 +01:00
spec - > gen . beep_nid = 0x23 ;
2011-07-07 18:23:21 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_pick_fixup ( codec , NULL , alc861vd_fixup_tbl , alc861vd_fixups ) ;
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PRE_PROBE ) ;
2011-07-07 18:23:21 +02:00
2011-08-23 17:34:25 +02:00
/* automatic parse from the BIOS config */
err = alc861vd_parse_auto_config ( codec ) ;
2011-10-17 16:39:09 +02:00
if ( err < 0 )
goto error ;
2011-04-27 16:35:23 +02:00
2013-03-18 11:25:51 +01:00
if ( ! spec - > gen . no_analog )
2011-07-08 16:55:13 +02:00
set_beep_amp ( spec , 0x0b , 0x05 , HDA_INPUT ) ;
2011-07-07 18:23:21 +02:00
codec - > patch_ops = alc_patch_ops ;
spec - > shutup = alc_eapd_shutup ;
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PROBE ) ;
2012-02-20 15:47:55 +01:00
2011-04-27 16:35:23 +02:00
return 0 ;
2011-10-17 16:39:09 +02:00
error :
alc_free ( codec ) ;
return err ;
2011-04-27 16:35:23 +02:00
}
2011-07-07 18:23:21 +02:00
/*
* ALC662 support
*
* ALC662 is almost identical with ALC880 but has cleaner and more flexible
* configuration . Each pin widget can choose any input DACs and a mixer .
* Each ADC is connected from a mixer of all inputs . This makes possible
* 6 - channel independent captures .
*
* In addition , an independent DAC for the multi - playback ( not used in this
* driver yet ) .
*/
/*
* BIOS auto configuration
*/
2007-04-12 13:06:07 +02:00
static int alc662_parse_auto_config ( struct hda_codec * codec )
{
2011-05-02 11:30:18 +02:00
static const hda_nid_t alc662_ignore [ ] = { 0x1d , 0 } ;
2011-07-08 16:55:13 +02:00
static const hda_nid_t alc663_ssids [ ] = { 0x15 , 0x1b , 0x14 , 0x21 } ;
static const hda_nid_t alc662_ssids [ ] = { 0x15 , 0x1b , 0x14 , 0 } ;
const hda_nid_t * ssids ;
2008-09-02 15:42:20 +02:00
2010-02-25 08:36:52 +01:00
if ( codec - > vendor_id = = 0x10ec0272 | | codec - > vendor_id = = 0x10ec0663 | |
codec - > vendor_id = = 0x10ec0665 | | codec - > vendor_id = = 0x10ec0670 )
2011-07-08 16:55:13 +02:00
ssids = alc663_ssids ;
2010-02-25 08:36:52 +01:00
else
2011-07-08 16:55:13 +02:00
ssids = alc662_ssids ;
return alc_parse_auto_config ( codec , alc662_ignore , ssids ) ;
2007-04-12 13:06:07 +02:00
}
2010-12-07 16:51:05 -08:00
static void alc272_fixup_mario ( struct hda_codec * codec ,
2013-01-10 09:52:52 +01:00
const struct hda_fixup * fix , int action )
2011-01-13 14:36:37 +01:00
{
2013-01-10 17:14:29 +01:00
if ( action ! = HDA_FIXUP_ACT_PRE_PROBE )
2011-01-13 14:36:37 +01:00
return ;
2010-12-07 16:51:05 -08:00
if ( snd_hda_override_amp_caps ( codec , 0x2 , HDA_OUTPUT ,
( 0x3b < < AC_AMPCAP_OFFSET_SHIFT ) |
( 0x3b < < AC_AMPCAP_NUM_STEPS_SHIFT ) |
( 0x03 < < AC_AMPCAP_STEP_SIZE_SHIFT ) |
( 0 < < AC_AMPCAP_MUTE_SHIFT ) ) )
printk ( KERN_WARNING
" hda_codec: failed to override amp caps for NID 0x2 \n " ) ;
}
2010-09-09 08:51:44 +02:00
enum {
2010-10-10 22:39:28 -04:00
ALC662_FIXUP_ASPIRE ,
2010-09-09 08:51:44 +02:00
ALC662_FIXUP_IDEAPAD ,
2010-12-07 16:51:05 -08:00
ALC272_FIXUP_MARIO ,
2011-01-20 12:36:21 +01:00
ALC662_FIXUP_CZC_P10T ,
2011-04-29 14:10:55 +02:00
ALC662_FIXUP_SKU_IGNORE ,
2011-06-29 17:21:00 +02:00
ALC662_FIXUP_HP_RP5800 ,
2011-08-23 18:27:14 +02:00
ALC662_FIXUP_ASUS_MODE1 ,
ALC662_FIXUP_ASUS_MODE2 ,
ALC662_FIXUP_ASUS_MODE3 ,
ALC662_FIXUP_ASUS_MODE4 ,
ALC662_FIXUP_ASUS_MODE5 ,
ALC662_FIXUP_ASUS_MODE6 ,
ALC662_FIXUP_ASUS_MODE7 ,
ALC662_FIXUP_ASUS_MODE8 ,
2012-02-13 12:03:25 +01:00
ALC662_FIXUP_NO_JACK_DETECT ,
2012-06-12 13:15:12 +02:00
ALC662_FIXUP_ZOTAC_Z68 ,
2012-06-22 14:30:29 +02:00
ALC662_FIXUP_INV_DMIC ,
2010-09-09 08:51:44 +02:00
} ;
2013-01-10 09:52:52 +01:00
static const struct hda_fixup alc662_fixups [ ] = {
2010-10-10 22:39:28 -04:00
[ ALC662_FIXUP_ASPIRE ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2010-10-10 22:39:28 -04:00
{ 0x15 , 0x99130112 } , /* subwoofer */
{ }
}
} ,
2010-09-09 08:51:44 +02:00
[ ALC662_FIXUP_IDEAPAD ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2010-09-09 08:51:44 +02:00
{ 0x17 , 0x99130112 } , /* subwoofer */
{ }
}
} ,
2010-12-07 16:51:05 -08:00
[ ALC272_FIXUP_MARIO ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2011-01-13 14:22:32 +01:00
. v . func = alc272_fixup_mario ,
2011-01-20 12:36:21 +01:00
} ,
[ ALC662_FIXUP_CZC_P10T ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_VERBS ,
2011-01-20 12:36:21 +01:00
. v . verbs = ( const struct hda_verb [ ] ) {
{ 0x14 , AC_VERB_SET_EAPD_BTLENABLE , 0 } ,
{ }
}
} ,
2011-04-29 14:10:55 +02:00
[ ALC662_FIXUP_SKU_IGNORE ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-05-07 17:17:32 +02:00
. v . func = alc_fixup_sku_ignore ,
2011-03-28 12:05:31 +02:00
} ,
2011-06-29 17:21:00 +02:00
[ ALC662_FIXUP_HP_RP5800 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-06-29 17:21:00 +02:00
{ 0x14 , 0x0221201f } , /* HP out */
{ }
} ,
. chained = true ,
. chain_id = ALC662_FIXUP_SKU_IGNORE
} ,
2011-08-23 18:27:14 +02:00
[ ALC662_FIXUP_ASUS_MODE1 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:27:14 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x18 , 0x01a19c20 } , /* mic */
{ 0x19 , 0x99a3092f } , /* int-mic */
{ 0x21 , 0x0121401f } , /* HP out */
{ }
} ,
. chained = true ,
. chain_id = ALC662_FIXUP_SKU_IGNORE
} ,
[ ALC662_FIXUP_ASUS_MODE2 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-18 16:02:24 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x18 , 0x01a19820 } , /* mic */
{ 0x19 , 0x99a3092f } , /* int-mic */
{ 0x1b , 0x0121401f } , /* HP out */
{ }
} ,
2011-08-23 18:27:14 +02:00
. chained = true ,
. chain_id = ALC662_FIXUP_SKU_IGNORE
} ,
[ ALC662_FIXUP_ASUS_MODE3 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:27:14 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x15 , 0x0121441f } , /* HP */
{ 0x18 , 0x01a19840 } , /* mic */
{ 0x19 , 0x99a3094f } , /* int-mic */
{ 0x21 , 0x01211420 } , /* HP2 */
{ }
} ,
. chained = true ,
. chain_id = ALC662_FIXUP_SKU_IGNORE
} ,
[ ALC662_FIXUP_ASUS_MODE4 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:27:14 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x16 , 0x99130111 } , /* speaker */
{ 0x18 , 0x01a19840 } , /* mic */
{ 0x19 , 0x99a3094f } , /* int-mic */
{ 0x21 , 0x0121441f } , /* HP */
{ }
} ,
. chained = true ,
. chain_id = ALC662_FIXUP_SKU_IGNORE
} ,
[ ALC662_FIXUP_ASUS_MODE5 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:27:14 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x15 , 0x0121441f } , /* HP */
{ 0x16 , 0x99130111 } , /* speaker */
{ 0x18 , 0x01a19840 } , /* mic */
{ 0x19 , 0x99a3094f } , /* int-mic */
{ }
} ,
. chained = true ,
. chain_id = ALC662_FIXUP_SKU_IGNORE
} ,
[ ALC662_FIXUP_ASUS_MODE6 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:27:14 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x15 , 0x01211420 } , /* HP2 */
{ 0x18 , 0x01a19840 } , /* mic */
{ 0x19 , 0x99a3094f } , /* int-mic */
{ 0x1b , 0x0121441f } , /* HP */
{ }
} ,
. chained = true ,
. chain_id = ALC662_FIXUP_SKU_IGNORE
} ,
[ ALC662_FIXUP_ASUS_MODE7 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:27:14 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x17 , 0x99130111 } , /* speaker */
{ 0x18 , 0x01a19840 } , /* mic */
{ 0x19 , 0x99a3094f } , /* int-mic */
{ 0x1b , 0x01214020 } , /* HP */
{ 0x21 , 0x0121401f } , /* HP */
{ }
} ,
. chained = true ,
. chain_id = ALC662_FIXUP_SKU_IGNORE
} ,
[ ALC662_FIXUP_ASUS_MODE8 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2011-08-23 18:27:14 +02:00
{ 0x14 , 0x99130110 } , /* speaker */
{ 0x12 , 0x99a30970 } , /* int-mic */
{ 0x15 , 0x01214020 } , /* HP */
{ 0x17 , 0x99130111 } , /* speaker */
{ 0x18 , 0x01a19840 } , /* mic */
{ 0x21 , 0x0121401f } , /* HP */
{ }
} ,
. chained = true ,
. chain_id = ALC662_FIXUP_SKU_IGNORE
2011-08-18 16:02:24 +02:00
} ,
2012-02-13 12:03:25 +01:00
[ ALC662_FIXUP_NO_JACK_DETECT ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
2012-02-13 12:03:25 +01:00
. v . func = alc_fixup_no_jack_detect ,
} ,
2012-06-12 13:15:12 +02:00
[ ALC662_FIXUP_ZOTAC_Z68 ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_PINS ,
. v . pins = ( const struct hda_pintbl [ ] ) {
2012-06-12 13:15:12 +02:00
{ 0x1b , 0x02214020 } , /* Front HP */
{ }
}
} ,
2012-06-22 14:30:29 +02:00
[ ALC662_FIXUP_INV_DMIC ] = {
2013-01-10 09:52:52 +01:00
. type = HDA_FIXUP_FUNC ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
. v . func = alc_fixup_inv_dmic_0x12 ,
2012-06-22 14:30:29 +02:00
} ,
2010-09-09 08:51:44 +02:00
} ;
2011-05-02 11:30:18 +02:00
static const struct snd_pci_quirk alc662_fixup_tbl [ ] = {
2011-08-23 18:27:14 +02:00
SND_PCI_QUIRK ( 0x1019 , 0x9087 , " ECS " , ALC662_FIXUP_ASUS_MODE2 ) ,
2011-02-10 15:39:19 +01:00
SND_PCI_QUIRK ( 0x1025 , 0x0308 , " Acer Aspire 8942G " , ALC662_FIXUP_ASPIRE ) ,
2011-04-29 14:10:55 +02:00
SND_PCI_QUIRK ( 0x1025 , 0x031c , " Gateway NV79 " , ALC662_FIXUP_SKU_IGNORE ) ,
2012-06-22 14:30:29 +02:00
SND_PCI_QUIRK ( 0x1025 , 0x0349 , " eMachines eM250 " , ALC662_FIXUP_INV_DMIC ) ,
2010-10-10 22:39:28 -04:00
SND_PCI_QUIRK ( 0x1025 , 0x038b , " Acer Aspire 8943G " , ALC662_FIXUP_ASPIRE ) ,
2011-06-29 17:21:00 +02:00
SND_PCI_QUIRK ( 0x103c , 0x1632 , " HP RP5800 " , ALC662_FIXUP_HP_RP5800 ) ,
2012-02-13 12:03:25 +01:00
SND_PCI_QUIRK ( 0x1043 , 0x8469 , " ASUS mobo " , ALC662_FIXUP_NO_JACK_DETECT ) ,
2011-08-23 18:27:14 +02:00
SND_PCI_QUIRK ( 0x105b , 0x0cd6 , " Foxconn " , ALC662_FIXUP_ASUS_MODE2 ) ,
2010-11-20 10:20:35 -05:00
SND_PCI_QUIRK ( 0x144d , 0xc051 , " Samsung R720 " , ALC662_FIXUP_IDEAPAD ) ,
2010-10-01 22:24:08 +06:00
SND_PCI_QUIRK ( 0x17aa , 0x38af , " Lenovo Ideapad Y550P " , ALC662_FIXUP_IDEAPAD ) ,
2010-09-09 08:51:44 +02:00
SND_PCI_QUIRK ( 0x17aa , 0x3a0d , " Lenovo Ideapad Y550 " , ALC662_FIXUP_IDEAPAD ) ,
2012-06-12 13:15:12 +02:00
SND_PCI_QUIRK ( 0x19da , 0xa130 , " Zotac Z68 " , ALC662_FIXUP_ZOTAC_Z68 ) ,
2011-01-20 12:36:21 +01:00
SND_PCI_QUIRK ( 0x1b35 , 0x2206 , " CZC P10T " , ALC662_FIXUP_CZC_P10T ) ,
2011-08-23 18:27:14 +02:00
#if 0
/* Below is a quirk table taken from the old code.
* Basically the device should work as is without the fixup table .
* If BIOS doesn ' t give a proper info , enable the corresponding
* fixup entry .
2012-04-12 22:11:25 +02:00
*/
2011-08-23 18:27:14 +02:00
SND_PCI_QUIRK ( 0x1043 , 0x1000 , " ASUS N50Vm " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1092 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE3 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1173 , " ASUS K73Jn " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x11c3 , " ASUS M70V " , ALC662_FIXUP_ASUS_MODE3 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x11d3 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x11f3 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1203 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1303 , " ASUS G60J " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1333 , " ASUS G60Jx " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1339 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x13e3 , " ASUS N71JA " , ALC662_FIXUP_ASUS_MODE7 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1463 , " ASUS N71 " , ALC662_FIXUP_ASUS_MODE7 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x14d3 , " ASUS G72 " , ALC662_FIXUP_ASUS_MODE8 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1563 , " ASUS N90 " , ALC662_FIXUP_ASUS_MODE3 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x15d3 , " ASUS N50SF F50SF " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x16c3 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x16f3 , " ASUS K40C K50C " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1733 , " ASUS N81De " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1753 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1763 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE6 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1765 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE6 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1783 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1793 , " ASUS F50GX " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x17b3 , " ASUS F70SL " , ALC662_FIXUP_ASUS_MODE3 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x17f3 , " ASUS X58LE " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1813 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1823 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE5 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1833 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE6 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1843 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1853 , " ASUS F50Z " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1864 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1876 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1893 , " ASUS M50Vm " , ALC662_FIXUP_ASUS_MODE3 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1894 , " ASUS X55 " , ALC662_FIXUP_ASUS_MODE3 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x18b3 , " ASUS N80Vc " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x18c3 , " ASUS VX5 " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x18d3 , " ASUS N81Te " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x18f3 , " ASUS N505Tp " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1903 , " ASUS F5GL " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1913 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1933 , " ASUS F80Q " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1943 , " ASUS Vx3V " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1953 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1963 , " ASUS X71C " , ALC662_FIXUP_ASUS_MODE3 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1983 , " ASUS N5051A " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x1993 , " ASUS N20 " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x19b3 , " ASUS F7Z " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x19c3 , " ASUS F5Z/F6x " , ALC662_FIXUP_ASUS_MODE2 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x19e3 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE1 ) ,
SND_PCI_QUIRK ( 0x1043 , 0x19f3 , " ASUS NB " , ALC662_FIXUP_ASUS_MODE4 ) ,
# endif
2010-09-09 08:51:44 +02:00
{ }
} ;
2013-01-10 09:52:52 +01:00
static const struct hda_model_fixup alc662_fixup_models [ ] = {
2010-12-07 16:51:05 -08:00
{ . id = ALC272_FIXUP_MARIO , . name = " mario " } ,
2011-08-23 18:27:14 +02:00
{ . id = ALC662_FIXUP_ASUS_MODE1 , . name = " asus-mode1 " } ,
{ . id = ALC662_FIXUP_ASUS_MODE2 , . name = " asus-mode2 " } ,
{ . id = ALC662_FIXUP_ASUS_MODE3 , . name = " asus-mode3 " } ,
{ . id = ALC662_FIXUP_ASUS_MODE4 , . name = " asus-mode4 " } ,
{ . id = ALC662_FIXUP_ASUS_MODE5 , . name = " asus-mode5 " } ,
{ . id = ALC662_FIXUP_ASUS_MODE6 , . name = " asus-mode6 " } ,
{ . id = ALC662_FIXUP_ASUS_MODE7 , . name = " asus-mode7 " } ,
{ . id = ALC662_FIXUP_ASUS_MODE8 , . name = " asus-mode8 " } ,
ALSA: hda - Add inv-dmic model to possible Realtek codecs
For convenience, add "inv-dmic" model string for enabling the inverted
internal mic workaround to possible Realtek codecs, so far,
ALC882-variants, ALC262, ALC268, ALC269-variants, and ALC662-variants.
Also, the model strings for hardware inv-dmic workarounds,
"alc269-dmic" and "alc271-dmic", are added for ALC269(VA) and ALC271
codecs as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2012-06-25 10:52:25 +02:00
{ . id = ALC662_FIXUP_INV_DMIC , . name = " inv-dmic " } ,
2010-12-07 16:51:05 -08:00
{ }
} ;
2010-09-09 08:51:44 +02:00
2012-06-29 09:35:52 +02:00
static void alc662_fill_coef ( struct hda_codec * codec )
{
int val , coef ;
coef = alc_get_coef0 ( codec ) ;
switch ( codec - > vendor_id ) {
case 0x10ec0662 :
if ( ( coef & 0x00f0 ) = = 0x0030 ) {
val = alc_read_coef_idx ( codec , 0x4 ) ; /* EAPD Ctrl */
alc_write_coef_idx ( codec , 0x4 , val & ~ ( 1 < < 10 ) ) ;
}
break ;
case 0x10ec0272 :
case 0x10ec0273 :
case 0x10ec0663 :
case 0x10ec0665 :
case 0x10ec0670 :
case 0x10ec0671 :
case 0x10ec0672 :
val = alc_read_coef_idx ( codec , 0xd ) ; /* EAPD Ctrl */
alc_write_coef_idx ( codec , 0xd , val | ( 1 < < 14 ) ) ;
break ;
}
}
2010-09-09 08:51:44 +02:00
2011-07-07 18:23:21 +02:00
/*
*/
2007-04-12 13:06:07 +02:00
static int patch_alc662 ( struct hda_codec * codec )
{
struct alc_spec * spec ;
2012-05-07 18:03:15 +02:00
int err ;
2007-04-12 13:06:07 +02:00
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0x0b ) ;
if ( err < 0 )
return err ;
2007-04-12 13:06:07 +02:00
2012-05-07 18:03:15 +02:00
spec = codec - > spec ;
2011-06-27 10:52:59 +02:00
2011-08-23 18:27:14 +02:00
/* handle multiple HPs as is */
spec - > parse_flags = HDA_PINCFG_NO_HP_FIXUP ;
2008-06-04 12:39:38 +02:00
alc_fix_pll_init ( codec , 0x20 , 0x04 , 15 ) ;
2012-06-29 09:35:52 +02:00
spec - > init_hook = alc662_fill_coef ;
alc662_fill_coef ( codec ) ;
2013-01-10 09:52:52 +01:00
snd_hda_pick_fixup ( codec , alc662_fixup_models ,
2012-06-21 15:49:33 +02:00
alc662_fixup_tbl , alc662_fixups ) ;
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PRE_PROBE ) ;
2012-06-21 15:49:33 +02:00
alc_auto_parse_customize_define ( codec ) ;
2013-03-18 11:25:51 +01:00
if ( has_cdefine_beep ( codec ) )
spec - > gen . beep_nid = 0x01 ;
2011-10-17 16:50:59 +02:00
if ( ( alc_get_coef0 ( codec ) & ( 1 < < 14 ) ) & &
2011-10-17 16:39:09 +02:00
codec - > bus - > pci - > subsystem_vendor = = 0x1025 & &
spec - > cdefine . platform_type = = 1 ) {
if ( alc_codec_rename ( codec , " ALC272X " ) < 0 )
goto error ;
2011-10-17 16:00:35 +02:00
}
2009-12-03 10:07:50 +01:00
2011-08-24 18:08:07 +02:00
/* automatic parse from the BIOS config */
err = alc662_parse_auto_config ( codec ) ;
2011-10-17 16:39:09 +02:00
if ( err < 0 )
goto error ;
2007-04-12 13:06:07 +02:00
2013-03-18 11:25:51 +01:00
if ( ! spec - > gen . no_analog & & spec - > gen . beep_nid ) {
2010-03-19 11:23:45 +01:00
switch ( codec - > vendor_id ) {
case 0x10ec0662 :
set_beep_amp ( spec , 0x0b , 0x05 , HDA_INPUT ) ;
break ;
case 0x10ec0272 :
case 0x10ec0663 :
case 0x10ec0665 :
set_beep_amp ( spec , 0x0b , 0x04 , HDA_INPUT ) ;
break ;
case 0x10ec0273 :
set_beep_amp ( spec , 0x0b , 0x03 , HDA_INPUT ) ;
break ;
}
2010-02-04 14:18:18 +01:00
}
2008-01-10 16:53:55 +01:00
2007-04-12 13:06:07 +02:00
codec - > patch_ops = alc_patch_ops ;
2011-04-07 10:37:16 +02:00
spec - > shutup = alc_eapd_shutup ;
2010-09-09 08:51:44 +02:00
2013-01-10 09:52:52 +01:00
snd_hda_apply_fixup ( codec , HDA_FIXUP_ACT_PROBE ) ;
2012-02-20 15:47:55 +01:00
2007-04-12 13:06:07 +02:00
return 0 ;
2011-10-17 16:02:42 +02:00
2011-10-17 16:39:09 +02:00
error :
alc_free ( codec ) ;
return err ;
2011-05-18 11:51:15 +02:00
}
2010-06-23 16:25:26 +02:00
/*
* ALC680 support
*/
static int alc680_parse_auto_config ( struct hda_codec * codec )
{
2011-07-08 16:55:13 +02:00
return alc_parse_auto_config ( codec , NULL , NULL ) ;
2010-06-23 16:25:26 +02:00
}
/*
*/
static int patch_alc680 ( struct hda_codec * codec )
{
int err ;
2011-06-27 10:52:59 +02:00
/* ALC680 has no aa-loopback mixer */
2012-05-07 18:03:15 +02:00
err = alc_alloc_spec ( codec , 0 ) ;
if ( err < 0 )
return err ;
2011-06-27 10:52:59 +02:00
2011-08-15 13:21:48 +02:00
/* automatic parse from the BIOS config */
err = alc680_parse_auto_config ( codec ) ;
if ( err < 0 ) {
alc_free ( codec ) ;
return err ;
2010-06-23 16:25:26 +02:00
}
codec - > patch_ops = alc_patch_ops ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
/*
* patch entries
*/
2011-05-02 11:30:18 +02:00
static const struct hda_codec_preset snd_hda_preset_realtek [ ] = {
2011-05-18 11:52:36 +02:00
{ . id = 0x10ec0221 , . name = " ALC221 " , . patch = patch_alc269 } ,
2013-03-07 09:19:38 +01:00
{ . id = 0x10ec0233 , . name = " ALC233 " , . patch = patch_alc269 } ,
2005-04-16 15:20:36 -07:00
{ . id = 0x10ec0260 , . name = " ALC260 " , . patch = patch_alc260 } ,
2005-12-05 19:42:22 +01:00
{ . id = 0x10ec0262 , . name = " ALC262 " , . patch = patch_alc262 } ,
2007-12-13 16:52:54 +01:00
{ . id = 0x10ec0267 , . name = " ALC267 " , . patch = patch_alc268 } ,
2007-06-05 12:30:55 +02:00
{ . id = 0x10ec0268 , . name = " ALC268 " , . patch = patch_alc268 } ,
2007-12-13 16:52:54 +01:00
{ . id = 0x10ec0269 , . name = " ALC269 " , . patch = patch_alc269 } ,
2009-12-17 12:23:00 +01:00
{ . id = 0x10ec0270 , . name = " ALC270 " , . patch = patch_alc269 } ,
2008-10-15 11:22:09 +02:00
{ . id = 0x10ec0272 , . name = " ALC272 " , . patch = patch_alc662 } ,
2009-12-17 12:23:00 +01:00
{ . id = 0x10ec0275 , . name = " ALC275 " , . patch = patch_alc269 } ,
2011-05-18 11:52:36 +02:00
{ . id = 0x10ec0276 , . name = " ALC276 " , . patch = patch_alc269 } ,
2012-06-25 19:49:28 +02:00
{ . id = 0x10ec0280 , . name = " ALC280 " , . patch = patch_alc269 } ,
2012-07-18 07:38:46 +02:00
{ . id = 0x10ec0282 , . name = " ALC282 " , . patch = patch_alc269 } ,
2012-10-06 17:02:30 +02:00
{ . id = 0x10ec0283 , . name = " ALC283 " , . patch = patch_alc269 } ,
2013-01-10 10:25:48 +01:00
{ . id = 0x10ec0284 , . name = " ALC284 " , . patch = patch_alc269 } ,
2012-10-06 17:02:30 +02:00
{ . id = 0x10ec0290 , . name = " ALC290 " , . patch = patch_alc269 } ,
2012-11-21 08:57:58 +01:00
{ . id = 0x10ec0292 , . name = " ALC292 " , . patch = patch_alc269 } ,
2007-02-02 18:17:27 +01:00
{ . id = 0x10ec0861 , . rev = 0x100340 , . name = " ALC660 " ,
2007-04-12 13:06:07 +02:00
. patch = patch_alc861 } ,
2007-02-02 18:17:27 +01:00
{ . id = 0x10ec0660 , . name = " ALC660-VD " , . patch = patch_alc861vd } ,
{ . id = 0x10ec0861 , . name = " ALC861 " , . patch = patch_alc861 } ,
{ . id = 0x10ec0862 , . name = " ALC861-VD " , . patch = patch_alc861vd } ,
2007-04-12 13:06:07 +02:00
{ . id = 0x10ec0662 , . rev = 0x100002 , . name = " ALC662 rev2 " ,
2009-06-30 15:28:30 +02:00
. patch = patch_alc882 } ,
2007-04-12 13:06:07 +02:00
{ . id = 0x10ec0662 , . rev = 0x100101 , . name = " ALC662 rev1 " ,
. patch = patch_alc662 } ,
2011-10-18 14:07:51 +02:00
{ . id = 0x10ec0662 , . rev = 0x100300 , . name = " ALC662 rev3 " ,
. patch = patch_alc662 } ,
2008-05-27 12:05:31 +02:00
{ . id = 0x10ec0663 , . name = " ALC663 " , . patch = patch_alc662 } ,
2010-02-04 14:18:18 +01:00
{ . id = 0x10ec0665 , . name = " ALC665 " , . patch = patch_alc662 } ,
2012-11-08 10:25:37 +01:00
{ . id = 0x10ec0668 , . name = " ALC668 " , . patch = patch_alc662 } ,
2010-02-25 08:36:52 +01:00
{ . id = 0x10ec0670 , . name = " ALC670 " , . patch = patch_alc662 } ,
2010-06-23 16:25:26 +02:00
{ . id = 0x10ec0680 , . name = " ALC680 " , . patch = patch_alc680 } ,
2007-02-02 18:17:27 +01:00
{ . id = 0x10ec0880 , . name = " ALC880 " , . patch = patch_alc880 } ,
2005-04-16 15:20:36 -07:00
{ . id = 0x10ec0882 , . name = " ALC882 " , . patch = patch_alc882 } ,
2009-06-30 15:28:30 +02:00
{ . id = 0x10ec0883 , . name = " ALC883 " , . patch = patch_alc882 } ,
2008-09-30 15:49:13 +02:00
{ . id = 0x10ec0885 , . rev = 0x100101 , . name = " ALC889A " ,
2009-06-30 15:28:30 +02:00
. patch = patch_alc882 } ,
2008-04-16 14:13:29 +02:00
{ . id = 0x10ec0885 , . rev = 0x100103 , . name = " ALC889A " ,
2009-06-30 15:28:30 +02:00
. patch = patch_alc882 } ,
2005-12-05 19:42:22 +01:00
{ . id = 0x10ec0885 , . name = " ALC885 " , . patch = patch_alc882 } ,
2011-10-17 16:39:09 +02:00
{ . id = 0x10ec0887 , . name = " ALC887 " , . patch = patch_alc882 } ,
2008-10-15 11:18:05 +02:00
{ . id = 0x10ec0888 , . rev = 0x100101 , . name = " ALC1200 " ,
2009-06-30 15:28:30 +02:00
. patch = patch_alc882 } ,
2011-10-17 16:39:09 +02:00
{ . id = 0x10ec0888 , . name = " ALC888 " , . patch = patch_alc882 } ,
2009-06-30 15:28:30 +02:00
{ . id = 0x10ec0889 , . name = " ALC889 " , . patch = patch_alc882 } ,
2009-12-03 10:07:50 +01:00
{ . id = 0x10ec0892 , . name = " ALC892 " , . patch = patch_alc662 } ,
2011-10-17 16:39:09 +02:00
{ . id = 0x10ec0899 , . name = " ALC898 " , . patch = patch_alc882 } ,
2012-11-08 10:25:37 +01:00
{ . id = 0x10ec0900 , . name = " ALC1150 " , . patch = patch_alc882 } ,
2005-04-16 15:20:36 -07:00
{ } /* terminator */
} ;
2008-11-27 15:47:11 +01:00
MODULE_ALIAS ( " snd-hda-codec-id:10ec* " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " Realtek HD-audio codec " ) ;
static struct hda_codec_preset_list realtek_list = {
. preset = snd_hda_preset_realtek ,
. owner = THIS_MODULE ,
} ;
static int __init patch_realtek_init ( void )
{
return snd_hda_add_codec_preset ( & realtek_list ) ;
}
static void __exit patch_realtek_exit ( void )
{
snd_hda_delete_codec_preset ( & realtek_list ) ;
}
module_init ( patch_realtek_init )
module_exit ( patch_realtek_exit )