diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c7df01b72ca..af989f660cc 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -44,6 +44,7 @@ struct hda_vendor_id { | |||
44 | /* codec vendor labels */ | 44 | /* codec vendor labels */ |
45 | static struct hda_vendor_id hda_vendor_ids[] = { | 45 | static struct hda_vendor_id hda_vendor_ids[] = { |
46 | { 0x1002, "ATI" }, | 46 | { 0x1002, "ATI" }, |
47 | { 0x1013, "Cirrus Logic" }, | ||
47 | { 0x1057, "Motorola" }, | 48 | { 0x1057, "Motorola" }, |
48 | { 0x1095, "Silicon Image" }, | 49 | { 0x1095, "Silicon Image" }, |
49 | { 0x10de, "Nvidia" }, | 50 | { 0x10de, "Nvidia" }, |
@@ -150,7 +151,14 @@ make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
150 | { | 151 | { |
151 | u32 val; | 152 | u32 val; |
152 | 153 | ||
153 | val = (u32)(codec->addr & 0x0f) << 28; | 154 | if ((codec->addr & ~0xf) || (direct & ~1) || (nid & ~0x7f) || |
155 | (verb & ~0xfff) || (parm & ~0xffff)) { | ||
156 | printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x:%x\n", | ||
157 | codec->addr, direct, nid, verb, parm); | ||
158 | return ~0; | ||
159 | } | ||
160 | |||
161 | val = (u32)codec->addr << 28; | ||
154 | val |= (u32)direct << 27; | 162 | val |= (u32)direct << 27; |
155 | val |= (u32)nid << 20; | 163 | val |= (u32)nid << 20; |
156 | val |= verb << 8; | 164 | val |= verb << 8; |
@@ -167,6 +175,9 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, | |||
167 | struct hda_bus *bus = codec->bus; | 175 | struct hda_bus *bus = codec->bus; |
168 | int err; | 176 | int err; |
169 | 177 | ||
178 | if (cmd == ~0) | ||
179 | return -1; | ||
180 | |||
170 | if (res) | 181 | if (res) |
171 | *res = -1; | 182 | *res = -1; |
172 | again: | 183 | again: |
@@ -291,11 +302,20 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | |||
291 | unsigned int parm; | 302 | unsigned int parm; |
292 | int i, conn_len, conns; | 303 | int i, conn_len, conns; |
293 | unsigned int shift, num_elems, mask; | 304 | unsigned int shift, num_elems, mask; |
305 | unsigned int wcaps; | ||
294 | hda_nid_t prev_nid; | 306 | hda_nid_t prev_nid; |
295 | 307 | ||
296 | if (snd_BUG_ON(!conn_list || max_conns <= 0)) | 308 | if (snd_BUG_ON(!conn_list || max_conns <= 0)) |
297 | return -EINVAL; | 309 | return -EINVAL; |
298 | 310 | ||
311 | wcaps = get_wcaps(codec, nid); | ||
312 | if (!(wcaps & AC_WCAP_CONN_LIST) && | ||
313 | get_wcaps_type(wcaps) != AC_WID_VOL_KNB) { | ||
314 | snd_printk(KERN_WARNING "hda_codec: " | ||
315 | "connection list not available for 0x%x\n", nid); | ||
316 | return -EINVAL; | ||
317 | } | ||
318 | |||
299 | parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); | 319 | parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); |
300 | if (parm & AC_CLIST_LONG) { | 320 | if (parm & AC_CLIST_LONG) { |
301 | /* long form */ | 321 | /* long form */ |
@@ -316,6 +336,8 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | |||
316 | /* single connection */ | 336 | /* single connection */ |
317 | parm = snd_hda_codec_read(codec, nid, 0, | 337 | parm = snd_hda_codec_read(codec, nid, 0, |
318 | AC_VERB_GET_CONNECT_LIST, 0); | 338 | AC_VERB_GET_CONNECT_LIST, 0); |
339 | if (parm == -1 && codec->bus->rirb_error) | ||
340 | return -EIO; | ||
319 | conn_list[0] = parm & mask; | 341 | conn_list[0] = parm & mask; |
320 | return 1; | 342 | return 1; |
321 | } | 343 | } |
@@ -327,9 +349,12 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, | |||
327 | int range_val; | 349 | int range_val; |
328 | hda_nid_t val, n; | 350 | hda_nid_t val, n; |
329 | 351 | ||
330 | if (i % num_elems == 0) | 352 | if (i % num_elems == 0) { |
331 | parm = snd_hda_codec_read(codec, nid, 0, | 353 | parm = snd_hda_codec_read(codec, nid, 0, |
332 | AC_VERB_GET_CONNECT_LIST, i); | 354 | AC_VERB_GET_CONNECT_LIST, i); |
355 | if (parm == -1 && codec->bus->rirb_error) | ||
356 | return -EIO; | ||
357 | } | ||
333 | range_val = !!(parm & (1 << (shift-1))); /* ranges */ | 358 | range_val = !!(parm & (1 << (shift-1))); /* ranges */ |
334 | val = parm & mask; | 359 | val = parm & mask; |
335 | if (val == 0) { | 360 | if (val == 0) { |
@@ -727,8 +752,7 @@ static int read_pin_defaults(struct hda_codec *codec) | |||
727 | for (i = 0; i < codec->num_nodes; i++, nid++) { | 752 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
728 | struct hda_pincfg *pin; | 753 | struct hda_pincfg *pin; |
729 | unsigned int wcaps = get_wcaps(codec, nid); | 754 | unsigned int wcaps = get_wcaps(codec, nid); |
730 | unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >> | 755 | unsigned int wid_type = get_wcaps_type(wcaps); |
731 | AC_WCAP_TYPE_SHIFT; | ||
732 | if (wid_type != AC_WID_PIN) | 756 | if (wid_type != AC_WID_PIN) |
733 | continue; | 757 | continue; |
734 | pin = snd_array_new(&codec->init_pins); | 758 | pin = snd_array_new(&codec->init_pins); |
@@ -891,7 +915,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
891 | * Returns 0 if successful, or a negative error code. | 915 | * Returns 0 if successful, or a negative error code. |
892 | */ | 916 | */ |
893 | int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | 917 | int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, |
894 | int do_init, struct hda_codec **codecp) | 918 | struct hda_codec **codecp) |
895 | { | 919 | { |
896 | struct hda_codec *codec; | 920 | struct hda_codec *codec; |
897 | char component[31]; | 921 | char component[31]; |
@@ -984,11 +1008,6 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
984 | codec->afg ? codec->afg : codec->mfg, | 1008 | codec->afg ? codec->afg : codec->mfg, |
985 | AC_PWRST_D0); | 1009 | AC_PWRST_D0); |
986 | 1010 | ||
987 | if (do_init) { | ||
988 | err = snd_hda_codec_configure(codec); | ||
989 | if (err < 0) | ||
990 | goto error; | ||
991 | } | ||
992 | snd_hda_codec_proc_new(codec); | 1011 | snd_hda_codec_proc_new(codec); |
993 | 1012 | ||
994 | snd_hda_create_hwdep(codec); | 1013 | snd_hda_create_hwdep(codec); |
@@ -1042,6 +1061,7 @@ int snd_hda_codec_configure(struct hda_codec *codec) | |||
1042 | err = init_unsol_queue(codec->bus); | 1061 | err = init_unsol_queue(codec->bus); |
1043 | return err; | 1062 | return err; |
1044 | } | 1063 | } |
1064 | EXPORT_SYMBOL_HDA(snd_hda_codec_configure); | ||
1045 | 1065 | ||
1046 | /** | 1066 | /** |
1047 | * snd_hda_codec_setup_stream - set up the codec for streaming | 1067 | * snd_hda_codec_setup_stream - set up the codec for streaming |
@@ -2356,16 +2376,20 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
2356 | hda_nid_t nid; | 2376 | hda_nid_t nid; |
2357 | int i; | 2377 | int i; |
2358 | 2378 | ||
2359 | snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 2379 | /* this delay seems necessary to avoid click noise at power-down */ |
2380 | if (power_state == AC_PWRST_D3) | ||
2381 | msleep(100); | ||
2382 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
2360 | power_state); | 2383 | power_state); |
2361 | msleep(10); /* partial workaround for "azx_get_response timeout" */ | 2384 | /* partial workaround for "azx_get_response timeout" */ |
2385 | if (power_state == AC_PWRST_D0) | ||
2386 | msleep(10); | ||
2362 | 2387 | ||
2363 | nid = codec->start_nid; | 2388 | nid = codec->start_nid; |
2364 | for (i = 0; i < codec->num_nodes; i++, nid++) { | 2389 | for (i = 0; i < codec->num_nodes; i++, nid++) { |
2365 | unsigned int wcaps = get_wcaps(codec, nid); | 2390 | unsigned int wcaps = get_wcaps(codec, nid); |
2366 | if (wcaps & AC_WCAP_POWER) { | 2391 | if (wcaps & AC_WCAP_POWER) { |
2367 | unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >> | 2392 | unsigned int wid_type = get_wcaps_type(wcaps); |
2368 | AC_WCAP_TYPE_SHIFT; | ||
2369 | if (power_state == AC_PWRST_D3 && | 2393 | if (power_state == AC_PWRST_D3 && |
2370 | wid_type == AC_WID_PIN) { | 2394 | wid_type == AC_WID_PIN) { |
2371 | unsigned int pincap; | 2395 | unsigned int pincap; |
@@ -2573,7 +2597,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
2573 | case 20: | 2597 | case 20: |
2574 | case 24: | 2598 | case 24: |
2575 | case 32: | 2599 | case 32: |
2576 | if (maxbps >= 32) | 2600 | if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) |
2577 | val |= 0x40; | 2601 | val |= 0x40; |
2578 | else if (maxbps >= 24) | 2602 | else if (maxbps >= 24) |
2579 | val |= 0x30; | 2603 | val |= 0x30; |
@@ -2700,11 +2724,12 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
2700 | bps = 20; | 2724 | bps = 20; |
2701 | } | 2725 | } |
2702 | } | 2726 | } |
2703 | else if (streams == AC_SUPFMT_FLOAT32) { | 2727 | if (streams & AC_SUPFMT_FLOAT32) { |
2704 | /* should be exclusive */ | ||
2705 | formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; | 2728 | formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; |
2706 | bps = 32; | 2729 | if (!bps) |
2707 | } else if (streams == AC_SUPFMT_AC3) { | 2730 | bps = 32; |
2731 | } | ||
2732 | if (streams == AC_SUPFMT_AC3) { | ||
2708 | /* should be exclusive */ | 2733 | /* should be exclusive */ |
2709 | /* temporary hack: we have still no proper support | 2734 | /* temporary hack: we have still no proper support |
2710 | * for the direct AC3 stream... | 2735 | * for the direct AC3 stream... |
@@ -3102,7 +3127,7 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, | |||
3102 | tbl = q; | 3127 | tbl = q; |
3103 | 3128 | ||
3104 | if (tbl->value >= 0 && tbl->value < num_configs) { | 3129 | if (tbl->value >= 0 && tbl->value < num_configs) { |
3105 | #ifdef CONFIG_SND_DEBUG_DETECT | 3130 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
3106 | char tmp[10]; | 3131 | char tmp[10]; |
3107 | const char *model = NULL; | 3132 | const char *model = NULL; |
3108 | if (models) | 3133 | if (models) |
@@ -3655,8 +3680,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
3655 | end_nid = codec->start_nid + codec->num_nodes; | 3680 | end_nid = codec->start_nid + codec->num_nodes; |
3656 | for (nid = codec->start_nid; nid < end_nid; nid++) { | 3681 | for (nid = codec->start_nid; nid < end_nid; nid++) { |
3657 | unsigned int wid_caps = get_wcaps(codec, nid); | 3682 | unsigned int wid_caps = get_wcaps(codec, nid); |
3658 | unsigned int wid_type = | 3683 | unsigned int wid_type = get_wcaps_type(wid_caps); |
3659 | (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
3660 | unsigned int def_conf; | 3684 | unsigned int def_conf; |
3661 | short assoc, loc; | 3685 | short assoc, loc; |
3662 | 3686 | ||