aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeeja KP <jeeja.kp@intel.com>2017-02-07 08:39:55 -0500
committerMark Brown <broonie@kernel.org>2017-02-16 13:56:06 -0500
commit0324e51b5ba405cd2d66e9e95430f6b9562d0ac0 (patch)
tree45a3f3cdcabf0b7b4ccabd5093e585e74a43cb4b
parent625de2bf2ed1632cb74a4a38f8f09a2063fb74af (diff)
ASoC: hdac_hdmi: Add machine pin widget for each port
Represent each port as machine DAPM pin widget. This helps in enable/disable pin when monitor is connected/disconnected in case pcm is rendered to multiple ports. Create machine pin widgets and pin switch kcontrol for each port and report based on the pin status Signed-off-by: Jeeja KP <jeeja.kp@intel.com> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/hdac_hdmi.c130
-rw-r--r--sound/soc/codecs/hdac_hdmi.h2
2 files changed, 132 insertions, 0 deletions
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 0f2c1e823281..0a5510a3a8e1 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -95,6 +95,9 @@ struct hdac_hdmi_port {
95 int num_mux_nids; 95 int num_mux_nids;
96 hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; 96 hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
97 struct hdac_hdmi_eld eld; 97 struct hdac_hdmi_eld eld;
98 const char *jack_pin;
99 struct snd_soc_dapm_context *dapm;
100 const char *output_pin;
98}; 101};
99 102
100struct hdac_hdmi_pcm { 103struct hdac_hdmi_pcm {
@@ -149,6 +152,11 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
149{ 152{
150 struct hdac_ext_device *edev = port->pin->edev; 153 struct hdac_ext_device *edev = port->pin->edev;
151 154
155 if (is_connect)
156 snd_soc_dapm_enable_pin(port->dapm, port->jack_pin);
157 else
158 snd_soc_dapm_disable_pin(port->dapm, port->jack_pin);
159
152 if (is_connect) { 160 if (is_connect) {
153 /* 161 /*
154 * Report Jack connect event when a device is connected 162 * Report Jack connect event when a device is connected
@@ -174,6 +182,8 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm,
174 if (pcm->jack_event > 0) 182 if (pcm->jack_event > 0)
175 pcm->jack_event--; 183 pcm->jack_event--;
176 } 184 }
185
186 snd_soc_dapm_sync(port->dapm);
177} 187}
178 188
179/* MST supported verbs */ 189/* MST supported verbs */
@@ -1059,6 +1069,7 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm)
1059 SND_SOC_DAPM_POST_PMD); 1069 SND_SOC_DAPM_POST_PMD);
1060 if (ret < 0) 1070 if (ret < 0)
1061 return ret; 1071 return ret;
1072 pin->ports[j].output_pin = widgets[i].name;
1062 i++; 1073 i++;
1063 } 1074 }
1064 } 1075 }
@@ -1557,6 +1568,125 @@ static struct snd_pcm *hdac_hdmi_get_pcm_from_id(struct snd_soc_card *card,
1557 return NULL; 1568 return NULL;
1558} 1569}
1559 1570
1571/* create jack pin kcontrols */
1572static int create_fill_jack_kcontrols(struct snd_soc_card *card,
1573 struct hdac_ext_device *edev)
1574{
1575 struct hdac_hdmi_pin *pin;
1576 struct snd_kcontrol_new *kc;
1577 char kc_name[NAME_SIZE], xname[NAME_SIZE];
1578 char *name;
1579 int i = 0, j;
1580 struct snd_soc_codec *codec = edev->scodec;
1581 struct hdac_hdmi_priv *hdmi = edev->private_data;
1582
1583 kc = devm_kcalloc(codec->dev, hdmi->num_ports,
1584 sizeof(*kc), GFP_KERNEL);
1585
1586 if (!kc)
1587 return -ENOMEM;
1588
1589 list_for_each_entry(pin, &hdmi->pin_list, head) {
1590 for (j = 0; j < pin->num_ports; j++) {
1591 snprintf(xname, sizeof(xname), "hif%d-%d Jack",
1592 pin->nid, pin->ports[j].id);
1593 name = devm_kstrdup(codec->dev, xname, GFP_KERNEL);
1594 if (!name)
1595 return -ENOMEM;
1596 snprintf(kc_name, sizeof(kc_name), "%s Switch", xname);
1597 kc[i].name = devm_kstrdup(codec->dev, kc_name,
1598 GFP_KERNEL);
1599 if (!kc[i].name)
1600 return -ENOMEM;
1601
1602 kc[i].private_value = (unsigned long)name;
1603 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1604 kc[i].access = 0;
1605 kc[i].info = snd_soc_dapm_info_pin_switch;
1606 kc[i].put = snd_soc_dapm_put_pin_switch;
1607 kc[i].get = snd_soc_dapm_get_pin_switch;
1608 i++;
1609 }
1610 }
1611
1612 return snd_soc_add_card_controls(card, kc, i);
1613}
1614
1615int hdac_hdmi_jack_port_init(struct snd_soc_codec *codec,
1616 struct snd_soc_dapm_context *dapm)
1617{
1618 struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec);
1619 struct hdac_hdmi_priv *hdmi = edev->private_data;
1620 struct hdac_hdmi_pin *pin;
1621 struct snd_soc_dapm_widget *widgets;
1622 struct snd_soc_dapm_route *route;
1623 char w_name[NAME_SIZE];
1624 int i = 0, j, ret;
1625
1626 widgets = devm_kcalloc(dapm->dev, hdmi->num_ports,
1627 sizeof(*widgets), GFP_KERNEL);
1628
1629 if (!widgets)
1630 return -ENOMEM;
1631
1632 route = devm_kcalloc(dapm->dev, hdmi->num_ports,
1633 sizeof(*route), GFP_KERNEL);
1634 if (!route)
1635 return -ENOMEM;
1636
1637 /* create Jack DAPM widget */
1638 list_for_each_entry(pin, &hdmi->pin_list, head) {
1639 for (j = 0; j < pin->num_ports; j++) {
1640 snprintf(w_name, sizeof(w_name), "hif%d-%d Jack",
1641 pin->nid, pin->ports[j].id);
1642
1643 ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i],
1644 snd_soc_dapm_spk, NULL,
1645 w_name, NULL, NULL, 0, NULL, 0);
1646 if (ret < 0)
1647 return ret;
1648
1649 pin->ports[j].jack_pin = widgets[i].name;
1650 pin->ports[j].dapm = dapm;
1651
1652 /* add to route from Jack widget to output */
1653 hdac_hdmi_fill_route(&route[i], pin->ports[j].jack_pin,
1654 NULL, pin->ports[j].output_pin, NULL);
1655
1656 i++;
1657 }
1658 }
1659
1660 /* Add Route from Jack widget to the output widget */
1661 ret = snd_soc_dapm_new_controls(dapm, widgets, hdmi->num_ports);
1662 if (ret < 0)
1663 return ret;
1664
1665 ret = snd_soc_dapm_add_routes(dapm, route, hdmi->num_ports);
1666 if (ret < 0)
1667 return ret;
1668
1669 ret = snd_soc_dapm_new_widgets(dapm->card);
1670 if (ret < 0)
1671 return ret;
1672
1673 /* Add Jack Pin switch Kcontrol */
1674 ret = create_fill_jack_kcontrols(dapm->card, edev);
1675
1676 if (ret < 0)
1677 return ret;
1678
1679 /* default set the Jack Pin switch to OFF */
1680 list_for_each_entry(pin, &hdmi->pin_list, head) {
1681 for (j = 0; j < pin->num_ports; j++)
1682 snd_soc_dapm_disable_pin(pin->ports[j].dapm,
1683 pin->ports[j].jack_pin);
1684 }
1685
1686 return 0;
1687}
1688EXPORT_SYMBOL_GPL(hdac_hdmi_jack_port_init);
1689
1560int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, 1690int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device,
1561 struct snd_soc_jack *jack) 1691 struct snd_soc_jack *jack)
1562{ 1692{
diff --git a/sound/soc/codecs/hdac_hdmi.h b/sound/soc/codecs/hdac_hdmi.h
index bf7edb3227d2..dfc3a9cf7199 100644
--- a/sound/soc/codecs/hdac_hdmi.h
+++ b/sound/soc/codecs/hdac_hdmi.h
@@ -4,4 +4,6 @@
4int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm, 4int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm,
5 struct snd_soc_jack *jack); 5 struct snd_soc_jack *jack);
6 6
7int hdac_hdmi_jack_port_init(struct snd_soc_codec *codec,
8 struct snd_soc_dapm_context *dapm);
7#endif /* __HDAC_HDMI_H__ */ 9#endif /* __HDAC_HDMI_H__ */