diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 76 |
1 files changed, 60 insertions, 16 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 23201f3eeb12..9c3d7ac08068 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
31 | #include <sound/asoundef.h> | 31 | #include <sound/asoundef.h> |
32 | #include <sound/tlv.h> | ||
32 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
33 | #include "hda_local.h" | 34 | #include "hda_local.h" |
34 | 35 | ||
@@ -50,8 +51,10 @@ struct hda_vendor_id { | |||
50 | /* codec vendor labels */ | 51 | /* codec vendor labels */ |
51 | static struct hda_vendor_id hda_vendor_ids[] = { | 52 | static struct hda_vendor_id hda_vendor_ids[] = { |
52 | { 0x10ec, "Realtek" }, | 53 | { 0x10ec, "Realtek" }, |
54 | { 0x1057, "Motorola" }, | ||
53 | { 0x11d4, "Analog Devices" }, | 55 | { 0x11d4, "Analog Devices" }, |
54 | { 0x13f6, "C-Media" }, | 56 | { 0x13f6, "C-Media" }, |
57 | { 0x14f1, "Conexant" }, | ||
55 | { 0x434d, "C-Media" }, | 58 | { 0x434d, "C-Media" }, |
56 | { 0x8384, "SigmaTel" }, | 59 | { 0x8384, "SigmaTel" }, |
57 | {} /* terminator */ | 60 | {} /* terminator */ |
@@ -841,6 +844,31 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
841 | return change; | 844 | return change; |
842 | } | 845 | } |
843 | 846 | ||
847 | int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
848 | unsigned int size, unsigned int __user *_tlv) | ||
849 | { | ||
850 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
851 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
852 | int dir = get_amp_direction(kcontrol); | ||
853 | u32 caps, val1, val2; | ||
854 | |||
855 | if (size < 4 * sizeof(unsigned int)) | ||
856 | return -ENOMEM; | ||
857 | caps = query_amp_caps(codec, nid, dir); | ||
858 | val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25; | ||
859 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | ||
860 | val1 = ((int)val1) * ((int)val2); | ||
861 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | ||
862 | return -EFAULT; | ||
863 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) | ||
864 | return -EFAULT; | ||
865 | if (put_user(val1, _tlv + 2)) | ||
866 | return -EFAULT; | ||
867 | if (put_user(val2, _tlv + 3)) | ||
868 | return -EFAULT; | ||
869 | return 0; | ||
870 | } | ||
871 | |||
844 | /* switch */ | 872 | /* switch */ |
845 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 873 | int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
846 | { | 874 | { |
@@ -1477,10 +1505,10 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
1477 | formats |= SNDRV_PCM_FMTBIT_S32_LE; | 1505 | formats |= SNDRV_PCM_FMTBIT_S32_LE; |
1478 | if (val & AC_SUPPCM_BITS_32) | 1506 | if (val & AC_SUPPCM_BITS_32) |
1479 | bps = 32; | 1507 | bps = 32; |
1480 | else if (val & AC_SUPPCM_BITS_20) | ||
1481 | bps = 20; | ||
1482 | else if (val & AC_SUPPCM_BITS_24) | 1508 | else if (val & AC_SUPPCM_BITS_24) |
1483 | bps = 24; | 1509 | bps = 24; |
1510 | else if (val & AC_SUPPCM_BITS_20) | ||
1511 | bps = 20; | ||
1484 | } | 1512 | } |
1485 | } | 1513 | } |
1486 | else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ | 1514 | else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ |
@@ -1916,7 +1944,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1916 | 1944 | ||
1917 | /* front */ | 1945 | /* front */ |
1918 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); | 1946 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); |
1919 | if (mout->hp_nid) | 1947 | if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) |
1920 | /* headphone out will just decode front left/right (stereo) */ | 1948 | /* headphone out will just decode front left/right (stereo) */ |
1921 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); | 1949 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); |
1922 | /* extra outputs copied from front */ | 1950 | /* extra outputs copied from front */ |
@@ -1984,7 +2012,7 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
1984 | * in the order of front, rear, CLFE, side, ... | 2012 | * in the order of front, rear, CLFE, side, ... |
1985 | * | 2013 | * |
1986 | * If more extra outputs (speaker and headphone) are found, the pins are | 2014 | * If more extra outputs (speaker and headphone) are found, the pins are |
1987 | * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack | 2015 | * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack |
1988 | * is detected, one of speaker of HP pins is assigned as the primary | 2016 | * is detected, one of speaker of HP pins is assigned as the primary |
1989 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 2017 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
1990 | * if any analog output exists. | 2018 | * if any analog output exists. |
@@ -2046,14 +2074,26 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2046 | cfg->speaker_outs++; | 2074 | cfg->speaker_outs++; |
2047 | break; | 2075 | break; |
2048 | case AC_JACK_HP_OUT: | 2076 | case AC_JACK_HP_OUT: |
2049 | cfg->hp_pin = nid; | 2077 | if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) |
2078 | continue; | ||
2079 | cfg->hp_pins[cfg->hp_outs] = nid; | ||
2080 | cfg->hp_outs++; | ||
2050 | break; | 2081 | break; |
2051 | case AC_JACK_MIC_IN: | 2082 | case AC_JACK_MIC_IN: { |
2052 | if (loc == AC_JACK_LOC_FRONT) | 2083 | int preferred, alt; |
2053 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid; | 2084 | if (loc == AC_JACK_LOC_FRONT) { |
2054 | else | 2085 | preferred = AUTO_PIN_FRONT_MIC; |
2055 | cfg->input_pins[AUTO_PIN_MIC] = nid; | 2086 | alt = AUTO_PIN_MIC; |
2087 | } else { | ||
2088 | preferred = AUTO_PIN_MIC; | ||
2089 | alt = AUTO_PIN_FRONT_MIC; | ||
2090 | } | ||
2091 | if (!cfg->input_pins[preferred]) | ||
2092 | cfg->input_pins[preferred] = nid; | ||
2093 | else if (!cfg->input_pins[alt]) | ||
2094 | cfg->input_pins[alt] = nid; | ||
2056 | break; | 2095 | break; |
2096 | } | ||
2057 | case AC_JACK_LINE_IN: | 2097 | case AC_JACK_LINE_IN: |
2058 | if (loc == AC_JACK_LOC_FRONT) | 2098 | if (loc == AC_JACK_LOC_FRONT) |
2059 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; | 2099 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; |
@@ -2119,8 +2159,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2119 | cfg->speaker_outs, cfg->speaker_pins[0], | 2159 | cfg->speaker_outs, cfg->speaker_pins[0], |
2120 | cfg->speaker_pins[1], cfg->speaker_pins[2], | 2160 | cfg->speaker_pins[1], cfg->speaker_pins[2], |
2121 | cfg->speaker_pins[3], cfg->speaker_pins[4]); | 2161 | cfg->speaker_pins[3], cfg->speaker_pins[4]); |
2122 | snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n", | 2162 | snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
2123 | cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin); | 2163 | cfg->hp_outs, cfg->hp_pins[0], |
2164 | cfg->hp_pins[1], cfg->hp_pins[2], | ||
2165 | cfg->hp_pins[3], cfg->hp_pins[4]); | ||
2124 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 2166 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," |
2125 | " cd=0x%x, aux=0x%x\n", | 2167 | " cd=0x%x, aux=0x%x\n", |
2126 | cfg->input_pins[AUTO_PIN_MIC], | 2168 | cfg->input_pins[AUTO_PIN_MIC], |
@@ -2141,10 +2183,12 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2141 | sizeof(cfg->speaker_pins)); | 2183 | sizeof(cfg->speaker_pins)); |
2142 | cfg->speaker_outs = 0; | 2184 | cfg->speaker_outs = 0; |
2143 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | 2185 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); |
2144 | } else if (cfg->hp_pin) { | 2186 | } else if (cfg->hp_outs) { |
2145 | cfg->line_outs = 1; | 2187 | cfg->line_outs = cfg->hp_outs; |
2146 | cfg->line_out_pins[0] = cfg->hp_pin; | 2188 | memcpy(cfg->line_out_pins, cfg->hp_pins, |
2147 | cfg->hp_pin = 0; | 2189 | sizeof(cfg->hp_pins)); |
2190 | cfg->hp_outs = 0; | ||
2191 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
2148 | } | 2192 | } |
2149 | } | 2193 | } |
2150 | 2194 | ||