From c54728d8aa59283ece86cb745e5085ece8b4eedb Mon Sep 17 00:00:00 2001 From: Nicola Fagnani Date: Thu, 19 Jul 2007 23:28:52 +0200 Subject: [PATCH] [ALSA] hda-intel: support for iMac 24'' released on 09/2006 Basic audio support for the iMac 24'' model released on 09/2006, including headphone jack detection with automatic speaker muting. This iMac uses the Realtek ALC885 codec, not a Sigmatel one as in other models. Functionality has been tested for internal speakers, headphone and microphone. Signed-off-by: Nicola Fagnani Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- .../sound/alsa/ALSA-Configuration.txt | 1 + sound/pci/hda/patch_realtek.c | 74 ++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 5bb45cd5f0e6..241e26c4ff92 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -843,6 +843,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 6stack-dig 6-jack digital with SPDIF I/O arima Arima W820Di1 macpro MacPro support + imac24 iMac 24'' with jack detection w2jc ASUS W2JC auto auto-config reading BIOS (default) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5825d9958f34..9a47eec5a27b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -153,6 +153,7 @@ enum { ALC882_TARGA, ALC882_ASUS_A7J, ALC885_MACPRO, + ALC885_IMAC24, ALC882_AUTO, ALC882_MODEL_LAST, }; @@ -5118,6 +5119,60 @@ static struct hda_verb alc882_macpro_init_verbs[] = { { } }; +/* iMac 24 mixer. */ +static struct snd_kcontrol_new alc885_imac24_mixer[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT), + HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT), + { } /* end */ +}; + +/* iMac 24 init verbs. */ +static struct hda_verb alc885_imac24_init_verbs[] = { + /* Internal speakers: output 0 (0x0c) */ + {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, + /* Internal speakers: output 0 (0x0c) */ + {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, + /* Headphone: output 0 (0x0c) */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + /* Front Mic: input vref at 80% */ + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + { } +}; + +/* Toggle speaker-output according to the hp-jack state */ +static void alc885_imac24_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x14, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_update(codec, 0x18, 0, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x18, 1, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); + snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, + 0x80, present ? 0x80 : 0); +} + +/* Processes unsolicited events. */ +static void alc885_imac24_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + /* Headphone insertion or removal. */ + if ((res >> 26) == ALC880_HP_EVENT) + alc885_imac24_automute(codec); +} + static struct hda_verb alc882_targa_verbs[] = { {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, @@ -5338,6 +5393,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { [ALC882_ARIMA] = "arima", [ALC882_W2JC] = "w2jc", [ALC885_MACPRO] = "macpro", + [ALC885_IMAC24] = "imac24", [ALC882_AUTO] = "auto", }; @@ -5410,6 +5466,19 @@ static struct alc_config_preset alc882_presets[] = { .channel_mode = alc882_ch_modes, .input_mux = &alc882_capture_source, }, + [ALC885_IMAC24] = { + .mixers = { alc885_imac24_mixer }, + .init_verbs = { alc885_imac24_init_verbs }, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), + .dac_nids = alc882_dac_nids, + .dig_out_nid = ALC882_DIGOUT_NID, + .dig_in_nid = ALC882_DIGIN_NID, + .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), + .channel_mode = alc882_ch_modes, + .input_mux = &alc882_capture_source, + .unsol_event = alc885_imac24_unsol_event, + .init_hook = alc885_imac24_automute, + }, [ALC882_TARGA] = { .mixers = { alc882_targa_mixer, alc882_chmode_mixer, alc882_capture_mixer }, @@ -5582,6 +5651,9 @@ static int patch_alc882(struct hda_codec *codec) case 0x106b0c00: /* Mac Pro */ board_config = ALC885_MACPRO; break; + case 0x106b1000: /* iMac 24 */ + board_config = ALC885_IMAC24; + break; default: printk(KERN_INFO "hda_codec: Unknown model for ALC882, " "trying auto-probe from BIOS...\n"); @@ -5608,7 +5680,7 @@ static int patch_alc882(struct hda_codec *codec) if (board_config != ALC882_AUTO) setup_preset(spec, &alc882_presets[board_config]); - if (board_config == ALC885_MACPRO) { + if (board_config == ALC885_MACPRO || board_config == ALC885_IMAC24) { alc882_gpio_mute(codec, 0, 0); alc882_gpio_mute(codec, 1, 0); }