diff options
Diffstat (limited to 'sound/pci/hda/hda_generic.c')
-rw-r--r-- | sound/pci/hda/hda_generic.c | 114 |
1 files changed, 17 insertions, 97 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index bebc3f4a47ba..296628b6ffc2 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -39,7 +39,6 @@ | |||
39 | int snd_hda_gen_spec_init(struct hda_gen_spec *spec) | 39 | int snd_hda_gen_spec_init(struct hda_gen_spec *spec) |
40 | { | 40 | { |
41 | snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); | 41 | snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32); |
42 | snd_array_init(&spec->bind_ctls, sizeof(struct hda_bind_ctls *), 8); | ||
43 | snd_array_init(&spec->paths, sizeof(struct nid_path), 8); | 42 | snd_array_init(&spec->paths, sizeof(struct nid_path), 8); |
44 | mutex_init(&spec->pcm_mutex); | 43 | mutex_init(&spec->pcm_mutex); |
45 | return 0; | 44 | return 0; |
@@ -75,39 +74,11 @@ static void free_kctls(struct hda_gen_spec *spec) | |||
75 | snd_array_free(&spec->kctls); | 74 | snd_array_free(&spec->kctls); |
76 | } | 75 | } |
77 | 76 | ||
78 | static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec, | ||
79 | unsigned int nums, | ||
80 | struct hda_ctl_ops *ops) | ||
81 | { | ||
82 | struct hda_gen_spec *spec = codec->spec; | ||
83 | struct hda_bind_ctls **ctlp, *ctl; | ||
84 | ctlp = snd_array_new(&spec->bind_ctls); | ||
85 | if (!ctlp) | ||
86 | return NULL; | ||
87 | ctl = kzalloc(sizeof(*ctl) + sizeof(long) * (nums + 1), GFP_KERNEL); | ||
88 | *ctlp = ctl; | ||
89 | if (ctl) | ||
90 | ctl->ops = ops; | ||
91 | return ctl; | ||
92 | } | ||
93 | |||
94 | static void free_bind_ctls(struct hda_gen_spec *spec) | ||
95 | { | ||
96 | if (spec->bind_ctls.list) { | ||
97 | struct hda_bind_ctls **ctl = spec->bind_ctls.list; | ||
98 | int i; | ||
99 | for (i = 0; i < spec->bind_ctls.used; i++) | ||
100 | kfree(ctl[i]); | ||
101 | } | ||
102 | snd_array_free(&spec->bind_ctls); | ||
103 | } | ||
104 | |||
105 | void snd_hda_gen_spec_free(struct hda_gen_spec *spec) | 77 | void snd_hda_gen_spec_free(struct hda_gen_spec *spec) |
106 | { | 78 | { |
107 | if (!spec) | 79 | if (!spec) |
108 | return; | 80 | return; |
109 | free_kctls(spec); | 81 | free_kctls(spec); |
110 | free_bind_ctls(spec); | ||
111 | snd_array_free(&spec->paths); | 82 | snd_array_free(&spec->paths); |
112 | } | 83 | } |
113 | EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free); | 84 | EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free); |
@@ -1489,8 +1460,7 @@ static int create_multi_out_ctls(struct hda_codec *codec, | |||
1489 | return 0; | 1460 | return 0; |
1490 | } | 1461 | } |
1491 | 1462 | ||
1492 | static int create_extra_out(struct hda_codec *codec, hda_nid_t pin, | 1463 | static int create_extra_out(struct hda_codec *codec, int path_idx, |
1493 | hda_nid_t dac, int path_idx, | ||
1494 | const char *pfx, int cidx) | 1464 | const char *pfx, int cidx) |
1495 | { | 1465 | { |
1496 | struct nid_path *path; | 1466 | struct nid_path *path; |
@@ -1499,12 +1469,9 @@ static int create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
1499 | path = snd_hda_get_path_from_idx(codec, path_idx); | 1469 | path = snd_hda_get_path_from_idx(codec, path_idx); |
1500 | if (!path) | 1470 | if (!path) |
1501 | return 0; | 1471 | return 0; |
1502 | /* bind volume control will be created in the case of dac = 0 */ | 1472 | err = add_stereo_vol(codec, pfx, cidx, path); |
1503 | if (dac) { | 1473 | if (err < 0) |
1504 | err = add_stereo_vol(codec, pfx, cidx, path); | 1474 | return err; |
1505 | if (err < 0) | ||
1506 | return err; | ||
1507 | } | ||
1508 | err = add_stereo_sw(codec, pfx, cidx, path); | 1475 | err = add_stereo_sw(codec, pfx, cidx, path); |
1509 | if (err < 0) | 1476 | if (err < 0) |
1510 | return err; | 1477 | return err; |
@@ -1513,69 +1480,26 @@ static int create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
1513 | 1480 | ||
1514 | /* add playback controls for speaker and HP outputs */ | 1481 | /* add playback controls for speaker and HP outputs */ |
1515 | static int create_extra_outs(struct hda_codec *codec, int num_pins, | 1482 | static int create_extra_outs(struct hda_codec *codec, int num_pins, |
1516 | const hda_nid_t *pins, const hda_nid_t *dacs, | ||
1517 | const int *paths, const char *pfx) | 1483 | const int *paths, const char *pfx) |
1518 | { | 1484 | { |
1519 | struct hda_gen_spec *spec = codec->spec; | 1485 | int i; |
1520 | struct hda_bind_ctls *ctl; | ||
1521 | char name[44]; | ||
1522 | int i, n, err; | ||
1523 | |||
1524 | if (!num_pins || !pins[0]) | ||
1525 | return 0; | ||
1526 | |||
1527 | if (num_pins == 1) { | ||
1528 | hda_nid_t dac = *dacs; | ||
1529 | if (!dac) | ||
1530 | dac = spec->multiout.dac_nids[0]; | ||
1531 | return create_extra_out(codec, *pins, dac, paths[0], pfx, 0); | ||
1532 | } | ||
1533 | 1486 | ||
1534 | for (i = 0; i < num_pins; i++) { | 1487 | for (i = 0; i < num_pins; i++) { |
1535 | hda_nid_t dac; | 1488 | const char *name; |
1536 | if (dacs[num_pins - 1]) | 1489 | char tmp[44]; |
1537 | dac = dacs[i]; /* with individual volumes */ | 1490 | int err, idx = 0; |
1538 | else | 1491 | |
1539 | dac = 0; | 1492 | if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) |
1540 | if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) { | 1493 | name = "Bass Speaker"; |
1541 | err = create_extra_out(codec, pins[i], dac, paths[i], | 1494 | else if (num_pins >= 3) { |
1542 | "Bass Speaker", 0); | 1495 | snprintf(tmp, sizeof(tmp), "%s %s", |
1543 | } else if (num_pins >= 3) { | ||
1544 | snprintf(name, sizeof(name), "%s %s", | ||
1545 | pfx, channel_name[i]); | 1496 | pfx, channel_name[i]); |
1546 | err = create_extra_out(codec, pins[i], dac, paths[i], | 1497 | name = tmp; |
1547 | name, 0); | ||
1548 | } else { | 1498 | } else { |
1549 | err = create_extra_out(codec, pins[i], dac, paths[i], | 1499 | name = pfx; |
1550 | pfx, i); | 1500 | idx = i; |
1551 | } | 1501 | } |
1552 | if (err < 0) | 1502 | err = create_extra_out(codec, paths[i], name, idx); |
1553 | return err; | ||
1554 | } | ||
1555 | if (dacs[num_pins - 1]) | ||
1556 | return 0; | ||
1557 | |||
1558 | /* Let's create a bind-controls for volumes */ | ||
1559 | ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol); | ||
1560 | if (!ctl) | ||
1561 | return -ENOMEM; | ||
1562 | n = 0; | ||
1563 | for (i = 0; i < num_pins; i++) { | ||
1564 | hda_nid_t vol; | ||
1565 | struct nid_path *path; | ||
1566 | if (!pins[i] || !dacs[i]) | ||
1567 | continue; | ||
1568 | path = snd_hda_get_path_from_idx(codec, paths[i]); | ||
1569 | if (!path) | ||
1570 | continue; | ||
1571 | vol = look_for_out_vol_nid(codec, path); | ||
1572 | if (vol) | ||
1573 | ctl->values[n++] = | ||
1574 | HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT); | ||
1575 | } | ||
1576 | if (n) { | ||
1577 | snprintf(name, sizeof(name), "%s Playback Volume", pfx); | ||
1578 | err = add_control(spec, HDA_CTL_BIND_VOL, name, 0, (long)ctl); | ||
1579 | if (err < 0) | 1503 | if (err < 0) |
1580 | return err; | 1504 | return err; |
1581 | } | 1505 | } |
@@ -1586,8 +1510,6 @@ static int create_hp_out_ctls(struct hda_codec *codec) | |||
1586 | { | 1510 | { |
1587 | struct hda_gen_spec *spec = codec->spec; | 1511 | struct hda_gen_spec *spec = codec->spec; |
1588 | return create_extra_outs(codec, spec->autocfg.hp_outs, | 1512 | return create_extra_outs(codec, spec->autocfg.hp_outs, |
1589 | spec->autocfg.hp_pins, | ||
1590 | spec->multiout.hp_out_nid, | ||
1591 | spec->hp_paths, | 1513 | spec->hp_paths, |
1592 | "Headphone"); | 1514 | "Headphone"); |
1593 | } | 1515 | } |
@@ -1596,8 +1518,6 @@ static int create_speaker_out_ctls(struct hda_codec *codec) | |||
1596 | { | 1518 | { |
1597 | struct hda_gen_spec *spec = codec->spec; | 1519 | struct hda_gen_spec *spec = codec->spec; |
1598 | return create_extra_outs(codec, spec->autocfg.speaker_outs, | 1520 | return create_extra_outs(codec, spec->autocfg.speaker_outs, |
1599 | spec->autocfg.speaker_pins, | ||
1600 | spec->multiout.extra_out_nid, | ||
1601 | spec->speaker_paths, | 1521 | spec->speaker_paths, |
1602 | "Speaker"); | 1522 | "Speaker"); |
1603 | } | 1523 | } |