aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_generic.c')
-rw-r--r--sound/pci/hda/hda_generic.c114
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 @@
39int snd_hda_gen_spec_init(struct hda_gen_spec *spec) 39int 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
78static 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
94static 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
105void snd_hda_gen_spec_free(struct hda_gen_spec *spec) 77void 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}
113EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free); 84EXPORT_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
1492static int create_extra_out(struct hda_codec *codec, hda_nid_t pin, 1463static 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 */
1515static int create_extra_outs(struct hda_codec *codec, int num_pins, 1482static 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}