aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_conexant.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-10-06 11:01:27 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-10-06 11:01:27 -0400
commit907bc6c7fc7071b00083fc11e510e47dd93df45d (patch)
tree0697a608561522c00da9e1814974a2eb051bb96d /sound/pci/hda/patch_conexant.c
parentd2b247a8be57647d1745535acd58169fbcbe431a (diff)
parent2a0f5cb32772e9a9560209e241a80bfbbc31dbc3 (diff)
Merge branch 'for-2.6.32' into for-2.6.33
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r--sound/pci/hda/patch_conexant.c491
1 files changed, 490 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index ac868c59f9e3..3fbbc8c01e70 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -108,6 +108,8 @@ struct conexant_spec {
108 struct hda_input_mux private_imux; 108 struct hda_input_mux private_imux;
109 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 109 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
110 110
111 unsigned int dell_automute;
112 unsigned int port_d_mode;
111}; 113};
112 114
113static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, 115static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@@ -680,11 +682,13 @@ static struct hda_input_mux cxt5045_capture_source = {
680}; 682};
681 683
682static struct hda_input_mux cxt5045_capture_source_benq = { 684static struct hda_input_mux cxt5045_capture_source_benq = {
683 .num_items = 3, 685 .num_items = 5,
684 .items = { 686 .items = {
685 { "IntMic", 0x1 }, 687 { "IntMic", 0x1 },
686 { "ExtMic", 0x2 }, 688 { "ExtMic", 0x2 },
687 { "LineIn", 0x3 }, 689 { "LineIn", 0x3 },
690 { "CD", 0x4 },
691 { "Mixer", 0x0 },
688 } 692 }
689}; 693};
690 694
@@ -809,11 +813,19 @@ static struct snd_kcontrol_new cxt5045_mixers[] = {
809}; 813};
810 814
811static struct snd_kcontrol_new cxt5045_benq_mixers[] = { 815static struct snd_kcontrol_new cxt5045_benq_mixers[] = {
816 HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT),
817 HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT),
818 HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT),
819 HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x4, HDA_INPUT),
820
812 HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT), 821 HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT),
813 HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT), 822 HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT),
814 HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT), 823 HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT),
815 HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT), 824 HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT),
816 825
826 HDA_CODEC_VOLUME("Mixer Capture Volume", 0x1a, 0x0, HDA_INPUT),
827 HDA_CODEC_MUTE("Mixer Capture Switch", 0x1a, 0x0, HDA_INPUT),
828
817 {} 829 {}
818}; 830};
819 831
@@ -1908,6 +1920,480 @@ static int patch_cxt5051(struct hda_codec *codec)
1908 return 0; 1920 return 0;
1909} 1921}
1910 1922
1923/* Conexant 5066 specific */
1924
1925static hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
1926static hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
1927static hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
1928#define CXT5066_SPDIF_OUT 0x21
1929
1930static struct hda_channel_mode cxt5066_modes[1] = {
1931 { 2, NULL },
1932};
1933
1934static void cxt5066_update_speaker(struct hda_codec *codec)
1935{
1936 struct conexant_spec *spec = codec->spec;
1937 unsigned int pinctl;
1938
1939 snd_printdd("CXT5066: update speaker, hp_present=%d\n",
1940 spec->hp_present);
1941
1942 /* Port A (HP) */
1943 pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0;
1944 snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1945 pinctl);
1946
1947 /* Port D (HP/LO) */
1948 pinctl = ((spec->hp_present & 2) && spec->cur_eapd)
1949 ? spec->port_d_mode : 0;
1950 snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1951 pinctl);
1952
1953 /* CLASS_D AMP */
1954 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
1955 snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1956 pinctl);
1957
1958 if (spec->dell_automute) {
1959 /* DELL AIO Port Rule: PortA > PortD > IntSpk */
1960 pinctl = (!(spec->hp_present & 1) && spec->cur_eapd)
1961 ? PIN_OUT : 0;
1962 snd_hda_codec_write(codec, 0x1c, 0,
1963 AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
1964 }
1965}
1966
1967/* turn on/off EAPD (+ mute HP) as a master switch */
1968static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol,
1969 struct snd_ctl_elem_value *ucontrol)
1970{
1971 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1972
1973 if (!cxt_eapd_put(kcontrol, ucontrol))
1974 return 0;
1975
1976 cxt5066_update_speaker(codec);
1977 return 1;
1978}
1979
1980/* toggle input of built-in and mic jack appropriately */
1981static void cxt5066_automic(struct hda_codec *codec)
1982{
1983 static struct hda_verb ext_mic_present[] = {
1984 /* enable external mic, port B */
1985 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1986
1987 /* switch to external mic input */
1988 {0x17, AC_VERB_SET_CONNECT_SEL, 0},
1989
1990 /* disable internal mic, port C */
1991 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
1992 {}
1993 };
1994 static struct hda_verb ext_mic_absent[] = {
1995 /* enable internal mic, port C */
1996 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1997
1998 /* switch to internal mic input */
1999 {0x17, AC_VERB_SET_CONNECT_SEL, 1},
2000
2001 /* disable external mic, port B */
2002 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2003 {}
2004 };
2005 unsigned int present;
2006
2007 present = snd_hda_codec_read(codec, 0x1a, 0,
2008 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
2009 if (present) {
2010 snd_printdd("CXT5066: external microphone detected\n");
2011 snd_hda_sequence_write(codec, ext_mic_present);
2012 } else {
2013 snd_printdd("CXT5066: external microphone absent\n");
2014 snd_hda_sequence_write(codec, ext_mic_absent);
2015 }
2016}
2017
2018/* mute internal speaker if HP is plugged */
2019static void cxt5066_hp_automute(struct hda_codec *codec)
2020{
2021 struct conexant_spec *spec = codec->spec;
2022 unsigned int portA, portD;
2023
2024 /* Port A */
2025 portA = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0)
2026 & AC_PINSENSE_PRESENCE;
2027
2028 /* Port D */
2029 portD = (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0)
2030 & AC_PINSENSE_PRESENCE) << 1;
2031
2032 spec->hp_present = !!(portA | portD);
2033 snd_printdd("CXT5066: hp automute portA=%x portD=%x present=%d\n",
2034 portA, portD, spec->hp_present);
2035 cxt5066_update_speaker(codec);
2036}
2037
2038/* unsolicited event for jack sensing */
2039static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
2040{
2041 snd_printdd("CXT5066: unsol event %x (%x)\n", res, res >> 26);
2042 switch (res >> 26) {
2043 case CONEXANT_HP_EVENT:
2044 cxt5066_hp_automute(codec);
2045 break;
2046 case CONEXANT_MIC_EVENT:
2047 cxt5066_automic(codec);
2048 break;
2049 }
2050}
2051
2052static const struct hda_input_mux cxt5066_analog_mic_boost = {
2053 .num_items = 5,
2054 .items = {
2055 { "0dB", 0 },
2056 { "10dB", 1 },
2057 { "20dB", 2 },
2058 { "30dB", 3 },
2059 { "40dB", 4 },
2060 },
2061};
2062
2063static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol,
2064 struct snd_ctl_elem_info *uinfo)
2065{
2066 return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo);
2067}
2068
2069static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
2070 struct snd_ctl_elem_value *ucontrol)
2071{
2072 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2073 int val;
2074
2075 val = snd_hda_codec_read(codec, 0x17, 0,
2076 AC_VERB_GET_AMP_GAIN_MUTE, AC_AMP_GET_OUTPUT);
2077
2078 ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN;
2079 return 0;
2080}
2081
2082static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
2083 struct snd_ctl_elem_value *ucontrol)
2084{
2085 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2086 const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
2087 unsigned int idx;
2088
2089 if (!imux->num_items)
2090 return 0;
2091 idx = ucontrol->value.enumerated.item[0];
2092 if (idx >= imux->num_items)
2093 idx = imux->num_items - 1;
2094
2095 snd_hda_codec_write_cache(codec, 0x17, 0,
2096 AC_VERB_SET_AMP_GAIN_MUTE,
2097 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
2098 imux->items[idx].index);
2099
2100 return 1;
2101}
2102
2103static struct hda_input_mux cxt5066_capture_source = {
2104 .num_items = 4,
2105 .items = {
2106 { "Mic B", 0 },
2107 { "Mic C", 1 },
2108 { "Mic E", 2 },
2109 { "Mic F", 3 },
2110 },
2111};
2112
2113static struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
2114 .ops = &snd_hda_bind_vol,
2115 .values = {
2116 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
2117 HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
2118 0
2119 },
2120};
2121
2122static struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
2123 .ops = &snd_hda_bind_sw,
2124 .values = {
2125 HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
2126 HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
2127 0
2128 },
2129};
2130
2131static struct snd_kcontrol_new cxt5066_mixer_master[] = {
2132 HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
2133 {}
2134};
2135
2136static struct snd_kcontrol_new cxt5066_mixer_master_olpc[] = {
2137 {
2138 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2139 .name = "Master Playback Volume",
2140 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
2141 SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2142 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,
2143 .info = snd_hda_mixer_amp_volume_info,
2144 .get = snd_hda_mixer_amp_volume_get,
2145 .put = snd_hda_mixer_amp_volume_put,
2146 .tlv = { .c = snd_hda_mixer_amp_tlv },
2147 /* offset by 28 volume steps to limit minimum gain to -46dB */
2148 .private_value =
2149 HDA_COMPOSE_AMP_VAL_OFS(0x10, 3, 0, HDA_OUTPUT, 28),
2150 },
2151 {}
2152};
2153
2154static struct snd_kcontrol_new cxt5066_mixers[] = {
2155 {
2156 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2157 .name = "Master Playback Switch",
2158 .info = cxt_eapd_info,
2159 .get = cxt_eapd_get,
2160 .put = cxt5066_hp_master_sw_put,
2161 .private_value = 0x1d,
2162 },
2163
2164 {
2165 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2166 .name = "Analog Mic Boost Capture Enum",
2167 .info = cxt5066_mic_boost_mux_enum_info,
2168 .get = cxt5066_mic_boost_mux_enum_get,
2169 .put = cxt5066_mic_boost_mux_enum_put,
2170 },
2171
2172 HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
2173 HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others),
2174 {}
2175};
2176
2177static struct hda_verb cxt5066_init_verbs[] = {
2178 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
2179 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
2180 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
2181 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
2182
2183 /* Speakers */
2184 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2185 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2186
2187 /* HP, Amp */
2188 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2189 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2190
2191 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2192 {0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2193
2194 /* DAC1 */
2195 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2196
2197 /* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
2198 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2199 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2200 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
2201 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2202 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2203
2204 /* no digital microphone support yet */
2205 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2206
2207 /* Audio input selector */
2208 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2209
2210 /* SPDIF route: PCM */
2211 {0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
2212 {0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
2213
2214 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2215 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2216
2217 /* EAPD */
2218 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2219
2220 /* not handling these yet */
2221 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2222 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2223 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2224 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2225 {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2226 {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2227 {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2228 {0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
2229 { } /* end */
2230};
2231
2232static struct hda_verb cxt5066_init_verbs_olpc[] = {
2233 /* Port A: headphones */
2234 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2235 {0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2236
2237 /* Port B: external microphone */
2238 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2239
2240 /* Port C: internal microphone */
2241 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2242
2243 /* Port D: unused */
2244 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2245
2246 /* Port E: unused, but has primary EAPD */
2247 {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2248 {0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
2249
2250 /* Port F: unused */
2251 {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2252
2253 /* Port G: internal speakers */
2254 {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2255 {0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
2256
2257 /* DAC1 */
2258 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2259
2260 /* DAC2: unused */
2261 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2262
2263 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
2264 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2265 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2266 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2267 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2268 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2269 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2270 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2271 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2272 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2273 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2274 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2275
2276 /* Disable digital microphone port */
2277 {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2278
2279 /* Audio input selectors */
2280 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
2281 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
2282
2283 /* Disable SPDIF */
2284 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2285 {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2286
2287 /* enable unsolicited events for Port A and B */
2288 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
2289 {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
2290 { } /* end */
2291};
2292
2293static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
2294 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2295 { } /* end */
2296};
2297
2298/* initialize jack-sensing, too */
2299static int cxt5066_init(struct hda_codec *codec)
2300{
2301 snd_printdd("CXT5066: init\n");
2302 conexant_init(codec);
2303 if (codec->patch_ops.unsol_event) {
2304 cxt5066_hp_automute(codec);
2305 cxt5066_automic(codec);
2306 }
2307 return 0;
2308}
2309
2310enum {
2311 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
2312 CXT5066_DELL_LAPTOP, /* Dell Laptop */
2313 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
2314 CXT5066_MODELS
2315};
2316
2317static const char *cxt5066_models[CXT5066_MODELS] = {
2318 [CXT5066_LAPTOP] = "laptop",
2319 [CXT5066_DELL_LAPTOP] = "dell-laptop",
2320 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
2321};
2322
2323static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
2324 SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
2325 CXT5066_LAPTOP),
2326 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
2327 CXT5066_DELL_LAPTOP),
2328 {}
2329};
2330
2331static int patch_cxt5066(struct hda_codec *codec)
2332{
2333 struct conexant_spec *spec;
2334 int board_config;
2335
2336 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2337 if (!spec)
2338 return -ENOMEM;
2339 codec->spec = spec;
2340
2341 codec->patch_ops = conexant_patch_ops;
2342 codec->patch_ops.init = cxt5066_init;
2343
2344 spec->dell_automute = 0;
2345 spec->multiout.max_channels = 2;
2346 spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids);
2347 spec->multiout.dac_nids = cxt5066_dac_nids;
2348 spec->multiout.dig_out_nid = CXT5066_SPDIF_OUT;
2349 spec->num_adc_nids = 1;
2350 spec->adc_nids = cxt5066_adc_nids;
2351 spec->capsrc_nids = cxt5066_capsrc_nids;
2352 spec->input_mux = &cxt5066_capture_source;
2353
2354 spec->port_d_mode = PIN_HP;
2355
2356 spec->num_init_verbs = 1;
2357 spec->init_verbs[0] = cxt5066_init_verbs;
2358 spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes);
2359 spec->channel_mode = cxt5066_modes;
2360 spec->cur_adc = 0;
2361 spec->cur_adc_idx = 0;
2362
2363 board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
2364 cxt5066_models, cxt5066_cfg_tbl);
2365 switch (board_config) {
2366 default:
2367 case CXT5066_LAPTOP:
2368 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
2369 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2370 break;
2371 case CXT5066_DELL_LAPTOP:
2372 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
2373 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2374
2375 spec->port_d_mode = PIN_OUT;
2376 spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo;
2377 spec->num_init_verbs++;
2378 spec->dell_automute = 1;
2379 break;
2380 case CXT5066_OLPC_XO_1_5:
2381 codec->patch_ops.unsol_event = cxt5066_unsol_event;
2382 spec->init_verbs[0] = cxt5066_init_verbs_olpc;
2383 spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc;
2384 spec->mixers[spec->num_mixers++] = cxt5066_mixers;
2385 spec->port_d_mode = 0;
2386
2387 /* no S/PDIF out */
2388 spec->multiout.dig_out_nid = 0;
2389
2390 /* input source automatically selected */
2391 spec->input_mux = NULL;
2392 break;
2393 }
2394
2395 return 0;
2396}
1911 2397
1912/* 2398/*
1913 */ 2399 */
@@ -1919,12 +2405,15 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
1919 .patch = patch_cxt5047 }, 2405 .patch = patch_cxt5047 },
1920 { .id = 0x14f15051, .name = "CX20561 (Hermosa)", 2406 { .id = 0x14f15051, .name = "CX20561 (Hermosa)",
1921 .patch = patch_cxt5051 }, 2407 .patch = patch_cxt5051 },
2408 { .id = 0x14f15066, .name = "CX20582 (Pebble)",
2409 .patch = patch_cxt5066 },
1922 {} /* terminator */ 2410 {} /* terminator */
1923}; 2411};
1924 2412
1925MODULE_ALIAS("snd-hda-codec-id:14f15045"); 2413MODULE_ALIAS("snd-hda-codec-id:14f15045");
1926MODULE_ALIAS("snd-hda-codec-id:14f15047"); 2414MODULE_ALIAS("snd-hda-codec-id:14f15047");
1927MODULE_ALIAS("snd-hda-codec-id:14f15051"); 2415MODULE_ALIAS("snd-hda-codec-id:14f15051");
2416MODULE_ALIAS("snd-hda-codec-id:14f15066");
1928 2417
1929MODULE_LICENSE("GPL"); 2418MODULE_LICENSE("GPL");
1930MODULE_DESCRIPTION("Conexant HD-audio codec"); 2419MODULE_DESCRIPTION("Conexant HD-audio codec");