[alsa-devel] [PATCH 00/16] ASoC: hdac_hdmi: Enable MST audio
From: Jeeja KP jeeja.kp@intel.com
With the patch series "ASoC: hdmi: Preparatory work to support MST audio", the design is extended from pin to port mapping to handle MST usecases.
A pin is MST capable if pipe is valid value (i.e. not -1) in the notify callback. If pipe = -1, default port is 0 else port = pipe. A MST capable pin widget is programmed by first sending a verb to select the device/port and then the actual verb is sent to program the widget.
This patch series enables MST Audio by configuring MST capable pins and extended the jack handling to report event for ports. Now the jack events are based on port connect/disconnect. The design is also extended to support mapping of multiple port to a single converter.
Now with the introduction of multiple ports with a single pin, a pin widget is created to enable/disable path based on device connection. Required machine driver changes are done to handle this change.
Also use the ASoC jack instead of snd_jack framework to creates jacks in the machine driver.
Note: This patch series has dependency on the series "ASoC: hdmi: Preparatory work to support MST audio"
Jeeja KP (16): ASoC: hdac_hdmi: Add MST verb support ASoC: hdac_hdmi: Handle MST pin jack detection at boot/resume ASoc: hdac_hdmi: Configure pin verbs for MST ASoC: hdac_hdmi: Add support for multiple ports to a PCM ASoC: hdac_hdmi: Use ASoC jack instead of snd_jack ASoC: Intel: Skylake: Create ASoC jack for hdmi in rt286 machine ASoC: Intel: Skylake: Create ASoC jack for hdmi in skl_nau88l25_max98357a machine ASoC: Intel: Skylake: Create ASoC jack for hdmi in nau88l25_ssm4567 machine ASoC: Intel: bxt: Create ASoC jack for hdmi in bxt_rt298 machine ASoC: Intel: bxt: Create ASoC jack for hdmi in bxt_da7219_max98357 machine ASoC: hdac_hdmi: Add machine pin widget for each port ASoC: Intel: Skylake: Add jack port initialize in rt286 machine ASoC: Intel: Skylake: Add jack port initialize in nau88l25_max98357a machine ASoC: Intel: Skylake: Add jack port initialize in nau88l25_ssm4567 machine ASoC: Intel: bxt: Add jack port initialize in bxt_rt298 machine ASoC: Intel: bxt: Add jack port initialize in da7219_max98357a machine
sound/soc/codecs/hdac_hdmi.c | 438 +++++++++++++++++++----- sound/soc/codecs/hdac_hdmi.h | 5 +- sound/soc/intel/boards/bxt_da7219_max98357a.c | 26 +- sound/soc/intel/boards/bxt_rt298.c | 26 +- sound/soc/intel/boards/skl_nau88l25_max98357a.c | 30 +- sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 30 +- sound/soc/intel/boards/skl_rt286.c | 30 +- 7 files changed, 482 insertions(+), 103 deletions(-)
From: Jeeja KP jeeja.kp@intel.com
To support DP MST audio, new pin verbs/params are added. This patch adds helper functions to do following: o To set a specific port o To get the currently selected port o To get the length of port.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/codecs/hdac_hdmi.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 17a1ad3..84b7d6c 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -142,6 +142,76 @@ hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi, return pcm; }
+/* MST supported verbs */ +/* + * Get the no devices that can be connected to a port on the Pin widget. + */ +static int hdac_hdmi_get_port_len(struct hdac_ext_device *hdac, hda_nid_t nid) +{ + unsigned int caps; + unsigned int type, param; + + caps = get_wcaps(&hdac->hdac, nid); + type = get_wcaps_type(caps); + + if (!(caps & AC_WCAP_DIGITAL) || (type != AC_WID_PIN)) + return 0; + + param = snd_hdac_read_parm_uncached(&hdac->hdac, nid, + AC_PAR_DEVLIST_LEN); + if (param == -1) + return param; + + return param & AC_DEV_LIST_LEN_MASK; +} + +/* + * Get the port entry select on the pin. Return the port entry + * id selected on the pin. Return 0 means the first port entry + * is selected or MST is not supported. + */ +static int hdac_hdmi_port_select_get(struct hdac_ext_device *hdac, + struct hdac_hdmi_port *port) +{ + return snd_hdac_codec_read(&hdac->hdac, port->pin->nid, + 0, AC_VERB_GET_DEVICE_SEL, 0); +} + +/* + * Sets the selected port entry for the configuring Pin widget verb. + * returns error if port set is not equal to port get otherwise success + */ +static int hdac_hdmi_port_select_set(struct hdac_ext_device *hdac, + struct hdac_hdmi_port *port) +{ + int num_ports; + + if (!port->pin->mst_capable) + return 0; + + /* AC_PAR_DEVLIST_LEN is 0 based. */ + num_ports = hdac_hdmi_get_port_len(hdac, port->pin->nid); + + if (num_ports < 0) + return -EIO; + /* + * Device List Length is a 0 based integer value indicating the + * number of sink device that a MST Pin Widget can support. + */ + if (num_ports + 1 < port->id) + return 0; + + snd_hdac_codec_write(&hdac->hdac, port->pin->nid, 0, + AC_VERB_SET_DEVICE_SEL, port->id); + + if (port->id != hdac_hdmi_port_select_get(hdac, port)) + return -EIO; + + dev_dbg(&hdac->hdac.dev, "Selected the port=%d\n", port->id); + + return 0; +} + static struct hdac_hdmi_pcm *get_hdmi_pcm_from_id(struct hdac_hdmi_priv *hdmi, int pcm_idx) {
From: Jeeja KP jeeja.kp@intel.com
The ELD notification can be received asynchronously from the graphics side and this may happen just at the moment the sound driver is initializing and notification will be missed. Similarly at system resume, the notification is ignored as the ELD and connection states are updated in anyway at the end of the resume. So check the jack status in boot/resume by querying the port presence based on pin caps and report the jack status.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/codecs/hdac_hdmi.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 84b7d6c..c5527e8 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -1551,15 +1551,38 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device) } EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init);
+static void hdac_hdmi_present_sense_all_pins(struct hdac_ext_device *edev, + struct hdac_hdmi_priv *hdmi, bool detect_pin_caps) +{ + int i; + struct hdac_hdmi_pin *pin; + + list_for_each_entry(pin, &hdmi->pin_list, head) { + if (detect_pin_caps) { + + if (hdac_hdmi_get_port_len(edev, pin->nid) == 0) + pin->mst_capable = false; + else + pin->mst_capable = true; + } + + for (i = 0; i < pin->num_ports; i++) { + if (!pin->mst_capable && i > 0) + continue; + + hdac_hdmi_present_sense(pin, &pin->ports[i]); + } + } +} + static int hdmi_codec_probe(struct snd_soc_codec *codec) { struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); struct hdac_hdmi_priv *hdmi = edev->private_data; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(&codec->component); - struct hdac_hdmi_pin *pin; struct hdac_ext_link *hlink = NULL; - int ret, i; + int ret;
edev->scodec = codec;
@@ -1587,10 +1610,7 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec) return ret; }
- list_for_each_entry(pin, &hdmi->pin_list, head) - for (i = 0; i < pin->num_ports; i++) - hdac_hdmi_present_sense(pin, &pin->ports[i]); - + hdac_hdmi_present_sense_all_pins(edev, hdmi, true); /* Imp: Store the card pointer in hda_codec */ edev->card = dapm->card->snd_card;
@@ -1638,9 +1658,7 @@ static void hdmi_codec_complete(struct device *dev) { struct hdac_ext_device *edev = to_hda_ext_device(dev); struct hdac_hdmi_priv *hdmi = edev->private_data; - struct hdac_hdmi_pin *pin; struct hdac_device *hdac = &edev->hdac; - int i;
/* Power up afg */ snd_hdac_codec_read(hdac, hdac->afg, 0, AC_VERB_SET_POWER_STATE, @@ -1652,11 +1670,10 @@ static void hdmi_codec_complete(struct device *dev) /* * As the ELD notify callback request is not entertained while the * device is in suspend state. Need to manually check detection of - * all pins here. + * all pins here. pin capablity change is not support, so use the + * already set pin caps. */ - list_for_each_entry(pin, &hdmi->pin_list, head) - for (i = 0; i < pin->num_ports; i++) - hdac_hdmi_present_sense(pin, &pin->ports[i]); + hdac_hdmi_present_sense_all_pins(edev, hdmi, false);
pm_runtime_put_sync(&edev->hdac.dev); }
From: Jeeja KP jeeja.kp@intel.com
To enable stream on a specific port of a MST capable pin, the port needs to be selected before we configure the pin widget verb.
When port is selected, all the pin widget verb controlling the sink device operation will be directed to selected port. So add port selection before configuring the pin widget verb.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/codecs/hdac_hdmi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index c5527e8..6cf86a0a 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -448,6 +448,9 @@ static int hdac_hdmi_query_port_connlist(struct hdac_ext_device *hdac, return -EINVAL; }
+ if (hdac_hdmi_port_select_set(hdac, port) < 0) + return -EIO; + port->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid, port->mux_nids, HDA_MAX_CONNECTIONS); if (port->num_mux_nids == 0) @@ -687,6 +690,10 @@ static int hdac_hdmi_pin_output_widget_event(struct snd_soc_dapm_widget *w, if (!pcm) return -EIO;
+ /* set the device if pin is mst_capable */ + if (hdac_hdmi_port_select_set(edev, port) < 0) + return -EIO; + switch (event) { case SND_SOC_DAPM_PRE_PMU: hdac_hdmi_set_power_state(edev, port->pin->nid, AC_PWRST_D0); @@ -775,6 +782,11 @@ static int hdac_hdmi_pin_mux_widget_event(struct snd_soc_dapm_widget *w, kc = w->kcontrols[0];
mux_idx = dapm_kcontrol_get_value(kc); + + /* set the device if pin is mst_capable */ + if (hdac_hdmi_port_select_set(edev, port) < 0) + return -EIO; + if (mux_idx > 0) { snd_hdac_codec_write(&edev->hdac, port->pin->nid, 0, AC_VERB_SET_CONNECT_SEL, (mux_idx - 1));
From: Jeeja KP jeeja.kp@intel.com
Since we have the MST feature enabled and Pin-Port mux for user to select the converter routing, multiple port mapping to same converter needs to be supported.
To support multiple port mapped to same converter following changes are done for this:. o Add port list to pcm, so that multiple ports can be mapped to a PCM. o Jack reporting in case where multiple port are attached to same PCM. o Change hdac_hdmi_get_port_from_cvt(), channel_map, remove functions to parse through all ports mapped to same the PCM.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/codecs/hdac_hdmi.c | 168 +++++++++++++++++++++++++++++-------------- 1 file changed, 113 insertions(+), 55 deletions(-)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 6cf86a0a..f8b6e9f 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -89,6 +89,7 @@ struct hdac_hdmi_pin { };
struct hdac_hdmi_port { + struct list_head head; int id; struct hdac_hdmi_pin *pin; int num_mux_nids; @@ -99,7 +100,7 @@ struct hdac_hdmi_port { struct hdac_hdmi_pcm { struct list_head head; int pcm_id; - struct hdac_hdmi_port *port; + struct list_head port_list; struct hdac_hdmi_cvt *cvt; struct snd_jack *jack; int stream_tag; @@ -108,6 +109,7 @@ struct hdac_hdmi_pcm { bool chmap_set; unsigned char chmap[8]; /* ALSA API channel-map */ struct mutex lock; + int jack_event; };
struct hdac_hdmi_dai_port_map { @@ -142,6 +144,37 @@ hdac_hdmi_get_pcm_from_cvt(struct hdac_hdmi_priv *hdmi, return pcm; }
+static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, + struct hdac_hdmi_port *port, bool is_connect) +{ + struct hdac_ext_device *edev = port->pin->edev; + + if (is_connect) { + /* + * Report Jack connect event when a device is connected + * for the first time where same PCM is attached to multiple + * ports. + */ + if (pcm->jack_event == 0) { + dev_dbg(&edev->hdac.dev, + "jack report for pcm=%d\n", + pcm->pcm_id); + snd_jack_report(pcm->jack, SND_JACK_AVOUT); + } + pcm->jack_event++; + } else { + /* + * Report Jack disconnect event when a device is disconnected + * is the only last connected device when same PCM is attached + * to multiple ports. + */ + if (pcm->jack_event == 1) + snd_jack_report(pcm->jack, 0); + if (pcm->jack_event > 0) + pcm->jack_event--; + } +} + /* MST supported verbs */ /* * Get the no devices that can be connected to a port on the Pin widget. @@ -484,19 +517,24 @@ static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt(
list_for_each_entry(pcm, &hdmi->pcm_list, head) { if (pcm->cvt == cvt) { - port = pcm->port; - break; - } - } - - if (port) { - ret = hdac_hdmi_query_port_connlist(edev, port->pin, port); - if (ret < 0) - return NULL; + if (list_empty(&pcm->port_list)) + continue;
- for (i = 0; i < port->num_mux_nids; i++) { - if (port->mux_nids[i] == cvt->nid) - return port; + list_for_each_entry(port, &pcm->port_list, head) { + mutex_lock(&pcm->lock); + ret = hdac_hdmi_query_port_connlist(edev, + port->pin, port); + mutex_unlock(&pcm->lock); + if (ret < 0) + continue; + + for (i = 0; i < port->num_mux_nids; i++) { + if (port->mux_nids[i] == cvt->nid && + port->eld.monitor_present && + port->eld.eld_valid) + return port; + } + } } }
@@ -529,7 +567,6 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, */ if (!port) return 0; - if ((!port->eld.monitor_present) || (!port->eld.eld_valid)) {
@@ -645,13 +682,16 @@ static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev, { struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_pcm *pcm = NULL; + struct hdac_hdmi_port *p;
list_for_each_entry(pcm, &hdmi->pcm_list, head) { - if (!pcm->port) + if (list_empty(&pcm->port_list)) continue;
- if (pcm->port == port) - return pcm; + list_for_each_entry(p, &pcm->port_list, head) { + if (p->id == port->id && port->pin == p->pin) + return pcm; + } }
return NULL; @@ -802,6 +842,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int ret; + struct hdac_hdmi_port *p, *p_next; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); struct snd_soc_dapm_context *dapm = w->dapm; @@ -820,25 +861,30 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
mutex_lock(&hdmi->pin_mutex); list_for_each_entry(pcm, &hdmi->pcm_list, head) { - if (!pcm->port && pcm->port == port && - pcm->port->id == port->id) - pcm->port = NULL; + if (list_empty(&pcm->port_list)) + continue;
- /* - * Jack status is not reported during device probe as the - * PCMs are not registered by then. So report it here. - */ - if (!strcmp(cvt_name, pcm->cvt->name) && !pcm->port) { - pcm->port = port; - if (port->eld.monitor_present && port->eld.eld_valid) { - dev_dbg(&edev->hdac.dev, - "jack report for pcm=%d\n", - pcm->pcm_id); + list_for_each_entry_safe(p, p_next, &pcm->port_list, head) { + if (p == port && p->id == port->id && + p->pin == port->pin) { + hdac_hdmi_jack_report(pcm, port, false); + list_del(&p->head); + } + } + }
- snd_jack_report(pcm->jack, SND_JACK_AVOUT); + /* + * Jack status is not reported during device probe as the + * PCMs are not registered by then. So report it here. + */ + list_for_each_entry(pcm, &hdmi->pcm_list, head) { + if (!strcmp(cvt_name, pcm->cvt->name)) { + list_add_tail(&port->head, &pcm->port_list); + if (port->eld.monitor_present && port->eld.eld_valid) { + hdac_hdmi_jack_report(pcm, port, true); + mutex_unlock(&hdmi->pin_mutex); + return ret; } - mutex_unlock(&hdmi->pin_mutex); - return ret; } } mutex_unlock(&hdmi->pin_mutex); @@ -1186,7 +1232,7 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin,
if (!port->eld.monitor_present || !port->eld.eld_valid) {
- dev_dbg(&edev->hdac.dev, "%s: disconnect for pin:port %d:%d\n", + dev_err(&edev->hdac.dev, "%s: disconnect for pin:port %d:%d\n", __func__, pin->nid, port->id);
/* @@ -1194,25 +1240,16 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, * report jack here. It will be done in usermode mux * control select. */ - if (pcm) { - dev_dbg(&edev->hdac.dev, - "jack report for pcm=%d\n", pcm->pcm_id); - - snd_jack_report(pcm->jack, 0); - } + if (pcm) + hdac_hdmi_jack_report(pcm, port, false);
mutex_unlock(&hdmi->pin_mutex); return; }
if (port->eld.monitor_present && port->eld.eld_valid) { - if (pcm) { - dev_dbg(&edev->hdac.dev, - "jack report for pcm=%d\n", - pcm->pcm_id); - - snd_jack_report(pcm->jack, SND_JACK_AVOUT); - } + if (pcm) + hdac_hdmi_jack_report(pcm, port, true);
print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1, port->eld.eld_buffer, port->eld.eld_size, false); @@ -1540,8 +1577,9 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device) return -ENOMEM; pcm->pcm_id = device; pcm->cvt = hdmi->dai_map[dai->id].cvt; + pcm->jack_event = 0; mutex_init(&pcm->lock); - + INIT_LIST_HEAD(&pcm->port_list); snd_pcm = hdac_hdmi_get_pcm_from_id(dai->component->card, device); if (snd_pcm) { err = snd_hdac_add_chmap_ctls(snd_pcm, device, &hdmi->chmap); @@ -1716,13 +1754,17 @@ static void hdac_hdmi_set_chmap(struct hdac_device *hdac, int pcm_idx, struct hdac_ext_device *edev = to_ehdac_device(hdac); struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); - struct hdac_hdmi_port *port = pcm->port; + struct hdac_hdmi_port *port; + + if (list_empty(&pcm->port_list)) + return;
mutex_lock(&pcm->lock); pcm->chmap_set = true; memcpy(pcm->chmap, chmap, ARRAY_SIZE(pcm->chmap)); - if (prepared) - hdac_hdmi_setup_audio_infoframe(edev, pcm, port); + list_for_each_entry(port, &pcm->port_list, head) + if (prepared) + hdac_hdmi_setup_audio_infoframe(edev, pcm, port); mutex_unlock(&pcm->lock); }
@@ -1731,9 +1773,11 @@ static bool is_hdac_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx) struct hdac_ext_device *edev = to_ehdac_device(hdac); struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); - struct hdac_hdmi_port *port = pcm->port;
- return port ? true:false; + if (list_empty(&pcm->port_list)) + return false; + + return true; }
static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) @@ -1741,7 +1785,15 @@ static int hdac_hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx) struct hdac_ext_device *edev = to_ehdac_device(hdac); struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_pcm *pcm = get_hdmi_pcm_from_id(hdmi, pcm_idx); - struct hdac_hdmi_port *port = pcm->port; + struct hdac_hdmi_port *port; + + if (list_empty(&pcm->port_list)) + return 0; + + port = list_first_entry(&pcm->port_list, struct hdac_hdmi_port, head); + + if (!port) + return 0;
if (!port || !port->eld.eld_valid) return 0; @@ -1819,13 +1871,19 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) struct hdac_hdmi_pin *pin, *pin_next; struct hdac_hdmi_cvt *cvt, *cvt_next; struct hdac_hdmi_pcm *pcm, *pcm_next; + struct hdac_hdmi_port *port; int i;
snd_soc_unregister_codec(&edev->hdac.dev);
list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) { pcm->cvt = NULL; - pcm->port = NULL; + if (list_empty(&pcm->port_list)) + continue; + + list_for_each_entry(port, &pcm->port_list, head) + port = NULL; + list_del(&pcm->head); kfree(pcm); }
From: Jeeja KP jeeja.kp@intel.com
Use snd_soc_jack instead of snd_jack and create the jack in machine driver and pass the jack pointer to hdac_hdmi driver for jack reporting.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/codecs/hdac_hdmi.c | 19 ++++++++----------- sound/soc/codecs/hdac_hdmi.h | 3 ++- 2 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index f8b6e9f..0f2c1e8 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -102,7 +102,7 @@ struct hdac_hdmi_pcm { int pcm_id; struct list_head port_list; struct hdac_hdmi_cvt *cvt; - struct snd_jack *jack; + struct snd_soc_jack *jack; int stream_tag; int channels; int format; @@ -159,7 +159,8 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, dev_dbg(&edev->hdac.dev, "jack report for pcm=%d\n", pcm->pcm_id); - snd_jack_report(pcm->jack, SND_JACK_AVOUT); + snd_soc_jack_report(pcm->jack, SND_JACK_AVOUT, + SND_JACK_AVOUT); } pcm->jack_event++; } else { @@ -169,7 +170,7 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, * to multiple ports. */ if (pcm->jack_event == 1) - snd_jack_report(pcm->jack, 0); + snd_soc_jack_report(pcm->jack, 0, SND_JACK_AVOUT); if (pcm->jack_event > 0) pcm->jack_event--; } @@ -1556,13 +1557,11 @@ static struct snd_pcm *hdac_hdmi_get_pcm_from_id(struct snd_soc_card *card, return NULL; }
-int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device) +int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, + struct snd_soc_jack *jack) { - char jack_name[NAME_SIZE]; struct snd_soc_codec *codec = dai->codec; struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); - struct snd_soc_dapm_context *dapm = - snd_soc_component_get_dapm(&codec->component); struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_pcm *pcm; struct snd_pcm *snd_pcm; @@ -1578,6 +1577,7 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device) pcm->pcm_id = device; pcm->cvt = hdmi->dai_map[dai->id].cvt; pcm->jack_event = 0; + pcm->jack = jack; mutex_init(&pcm->lock); INIT_LIST_HEAD(&pcm->port_list); snd_pcm = hdac_hdmi_get_pcm_from_id(dai->component->card, device); @@ -1594,10 +1594,7 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device)
list_add_tail(&pcm->head, &hdmi->pcm_list);
- sprintf(jack_name, "HDMI/DP, pcm=%d Jack", device); - - return snd_jack_new(dapm->card->snd_card, jack_name, - SND_JACK_AVOUT, &pcm->jack, true, false); + return 0; } EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init);
diff --git a/sound/soc/codecs/hdac_hdmi.h b/sound/soc/codecs/hdac_hdmi.h index 8dfd1e0..bf7edb3 100644 --- a/sound/soc/codecs/hdac_hdmi.h +++ b/sound/soc/codecs/hdac_hdmi.h @@ -1,6 +1,7 @@ #ifndef __HDAC_HDMI_H__ #define __HDAC_HDMI_H__
-int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm); +int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm, + struct snd_soc_jack *jack);
#endif /* __HDAC_HDMI_H__ */
From: Jeeja KP jeeja.kp@intel.com
Creates ASoC jack for HDMI pcm and calls hdmi codec API to initialize jack in skl_rt268 machine
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/skl_rt286.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 5e56af3..11647b0 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -29,6 +29,7 @@ #include "../../codecs/hdac_hdmi.h"
static struct snd_soc_jack skylake_headset; +static struct snd_soc_jack skylake_hdmi[3];
struct skl_hdmi_pcm { struct list_head head; @@ -458,16 +459,30 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { }, };
+#define NAME_SIZE 32 static int skylake_card_late_probe(struct snd_soc_card *card) { struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(card); struct skl_hdmi_pcm *pcm; - int err; + int err, i = 0; + char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device); + snprintf(jack_name, sizeof(jack_name), + "HDMI/DP, pcm=%d Jack", pcm->device); + err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_AVOUT, &skylake_hdmi[i], + NULL, 0); + + if (err) + return err; + + err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, + &skylake_hdmi[i]); if (err < 0) return err; + + i++; }
return 0;
From: Jeeja KP jeeja.kp@intel.com
Creates ASoC jack for HDMI PCM and calls hdmi codec API to initialize jack in skl_nau88l25_max98357a machine
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/skl_nau88l25_max98357a.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index bb41968..48f7c96 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -32,6 +32,7 @@ static struct snd_soc_jack skylake_headset; static struct snd_soc_card skylake_audio_card; static const struct snd_pcm_hw_constraint_list *dmic_constraints; +static struct snd_soc_jack skylake_hdmi[3];
struct skl_hdmi_pcm { struct list_head head; @@ -603,16 +604,31 @@ static struct snd_soc_dai_link skylake_dais[] = { }, };
+#define NAME_SIZE 32 static int skylake_card_late_probe(struct snd_soc_card *card) { struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(card); struct skl_hdmi_pcm *pcm; - int err; + int err, i = 0; + char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device); + snprintf(jack_name, sizeof(jack_name), + "HDMI/DP, pcm=%d Jack", pcm->device); + err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_AVOUT, + &skylake_hdmi[i], + NULL, 0); + + if (err) + return err; + + err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, + &skylake_hdmi[i]); if (err < 0) return err; + + i++; }
return 0;
From: Jeeja KP jeeja.kp@intel.com
Creates ASoC jack for HDMI PCM and calls hdmi codec API to initialize jack in skl_nau88l25_ssm4567 machine
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index 41117bc..5deb68f 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -36,6 +36,7 @@ static struct snd_soc_jack skylake_headset; static struct snd_soc_card skylake_audio_card; static const struct snd_pcm_hw_constraint_list *dmic_constraints; +static struct snd_soc_jack skylake_hdmi[3];
struct skl_hdmi_pcm { struct list_head head; @@ -654,16 +655,31 @@ static struct snd_soc_dai_link skylake_dais[] = { }, };
+#define NAME_SIZE 32 static int skylake_card_late_probe(struct snd_soc_card *card) { struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(card); struct skl_hdmi_pcm *pcm; - int err; + int err, i = 0; + char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device); + snprintf(jack_name, sizeof(jack_name), + "HDMI/DP, pcm=%d Jack", pcm->device); + err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_AVOUT, + &skylake_hdmi[i], + NULL, 0); + + if (err) + return err; + + err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, + &skylake_hdmi[i]); if (err < 0) return err; + + i++; }
return 0;
From: Jeeja KP jeeja.kp@intel.com
Creates ASoC jack for HDMI PCM and calls hdmi codec API to initialize jack in bxt_rt298.c machine
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/bxt_rt298.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 09be868..d5f53a6 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -28,6 +28,7 @@
/* Headset jack detection DAPM pins */ static struct snd_soc_jack broxton_headset; +static struct snd_soc_jack broxton_hdmi[3];
struct bxt_hdmi_pcm { struct list_head head; @@ -453,16 +454,30 @@ static struct snd_soc_dai_link broxton_rt298_dais[] = { }, };
+#define NAME_SIZE 32 static int bxt_card_late_probe(struct snd_soc_card *card) { struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(card); struct bxt_hdmi_pcm *pcm; - int err; + int err, i = 0; + char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device); + snprintf(jack_name, sizeof(jack_name), + "HDMI/DP, pcm=%d Jack", pcm->device); + err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_AVOUT, &broxton_hdmi[i], + NULL, 0); + + if (err) + return err; + + err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, + &broxton_hdmi[i]); if (err < 0) return err; + + i++; }
return 0;
From: Jeeja KP jeeja.kp@intel.com
Creates ASoC jack for HDMI PCM and calls hdmi codec API to initialize jack in bxt_da7219_max98357 machine
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/bxt_da7219_max98357a.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index a9647a2..18f3d0e 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -33,6 +33,7 @@ #define QUAD_CHANNEL 4
static struct snd_soc_jack broxton_headset; +static struct snd_soc_jack broxton_hdmi[3];
struct bxt_hdmi_pcm { struct list_head head; @@ -517,16 +518,30 @@ static struct snd_soc_dai_link broxton_dais[] = { }, };
+#define NAME_SIZE 32 static int bxt_card_late_probe(struct snd_soc_card *card) { struct bxt_card_private *ctx = snd_soc_card_get_drvdata(card); struct bxt_hdmi_pcm *pcm; - int err; + int err, i = 0; + char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device); + snprintf(jack_name, sizeof(jack_name), + "HDMI/DP, pcm=%d Jack", pcm->device); + err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_AVOUT, &broxton_hdmi[i], + NULL, 0); + + if (err) + return err; + + err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, + &broxton_hdmi[i]); if (err < 0) return err; + + i++; }
return 0;
From: Jeeja KP jeeja.kp@intel.com
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 --- sound/soc/codecs/hdac_hdmi.c | 130 +++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/hdac_hdmi.h | 2 + 2 files changed, 132 insertions(+)
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 0f2c1e8..0a5510a 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -95,6 +95,9 @@ struct hdac_hdmi_port { int num_mux_nids; hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; struct hdac_hdmi_eld eld; + const char *jack_pin; + struct snd_soc_dapm_context *dapm; + const char *output_pin; };
struct hdac_hdmi_pcm { @@ -149,6 +152,11 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, { struct hdac_ext_device *edev = port->pin->edev;
+ if (is_connect) + snd_soc_dapm_enable_pin(port->dapm, port->jack_pin); + else + snd_soc_dapm_disable_pin(port->dapm, port->jack_pin); + if (is_connect) { /* * Report Jack connect event when a device is connected @@ -174,6 +182,8 @@ static void hdac_hdmi_jack_report(struct hdac_hdmi_pcm *pcm, if (pcm->jack_event > 0) pcm->jack_event--; } + + snd_soc_dapm_sync(port->dapm); }
/* MST supported verbs */ @@ -1059,6 +1069,7 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) SND_SOC_DAPM_POST_PMD); if (ret < 0) return ret; + pin->ports[j].output_pin = widgets[i].name; i++; } } @@ -1557,6 +1568,125 @@ static struct snd_pcm *hdac_hdmi_get_pcm_from_id(struct snd_soc_card *card, return NULL; }
+/* create jack pin kcontrols */ +static int create_fill_jack_kcontrols(struct snd_soc_card *card, + struct hdac_ext_device *edev) +{ + struct hdac_hdmi_pin *pin; + struct snd_kcontrol_new *kc; + char kc_name[NAME_SIZE], xname[NAME_SIZE]; + char *name; + int i = 0, j; + struct snd_soc_codec *codec = edev->scodec; + struct hdac_hdmi_priv *hdmi = edev->private_data; + + kc = devm_kcalloc(codec->dev, hdmi->num_ports, + sizeof(*kc), GFP_KERNEL); + + if (!kc) + return -ENOMEM; + + list_for_each_entry(pin, &hdmi->pin_list, head) { + for (j = 0; j < pin->num_ports; j++) { + snprintf(xname, sizeof(xname), "hif%d-%d Jack", + pin->nid, pin->ports[j].id); + name = devm_kstrdup(codec->dev, xname, GFP_KERNEL); + if (!name) + return -ENOMEM; + snprintf(kc_name, sizeof(kc_name), "%s Switch", xname); + kc[i].name = devm_kstrdup(codec->dev, kc_name, + GFP_KERNEL); + if (!kc[i].name) + return -ENOMEM; + + kc[i].private_value = (unsigned long)name; + kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; + kc[i].access = 0; + kc[i].info = snd_soc_dapm_info_pin_switch; + kc[i].put = snd_soc_dapm_put_pin_switch; + kc[i].get = snd_soc_dapm_get_pin_switch; + i++; + } + } + + return snd_soc_add_card_controls(card, kc, i); +} + +int hdac_hdmi_jack_port_init(struct snd_soc_codec *codec, + struct snd_soc_dapm_context *dapm) +{ + struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); + struct hdac_hdmi_priv *hdmi = edev->private_data; + struct hdac_hdmi_pin *pin; + struct snd_soc_dapm_widget *widgets; + struct snd_soc_dapm_route *route; + char w_name[NAME_SIZE]; + int i = 0, j, ret; + + widgets = devm_kcalloc(dapm->dev, hdmi->num_ports, + sizeof(*widgets), GFP_KERNEL); + + if (!widgets) + return -ENOMEM; + + route = devm_kcalloc(dapm->dev, hdmi->num_ports, + sizeof(*route), GFP_KERNEL); + if (!route) + return -ENOMEM; + + /* create Jack DAPM widget */ + list_for_each_entry(pin, &hdmi->pin_list, head) { + for (j = 0; j < pin->num_ports; j++) { + snprintf(w_name, sizeof(w_name), "hif%d-%d Jack", + pin->nid, pin->ports[j].id); + + ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i], + snd_soc_dapm_spk, NULL, + w_name, NULL, NULL, 0, NULL, 0); + if (ret < 0) + return ret; + + pin->ports[j].jack_pin = widgets[i].name; + pin->ports[j].dapm = dapm; + + /* add to route from Jack widget to output */ + hdac_hdmi_fill_route(&route[i], pin->ports[j].jack_pin, + NULL, pin->ports[j].output_pin, NULL); + + i++; + } + } + + /* Add Route from Jack widget to the output widget */ + ret = snd_soc_dapm_new_controls(dapm, widgets, hdmi->num_ports); + if (ret < 0) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, route, hdmi->num_ports); + if (ret < 0) + return ret; + + ret = snd_soc_dapm_new_widgets(dapm->card); + if (ret < 0) + return ret; + + /* Add Jack Pin switch Kcontrol */ + ret = create_fill_jack_kcontrols(dapm->card, edev); + + if (ret < 0) + return ret; + + /* default set the Jack Pin switch to OFF */ + list_for_each_entry(pin, &hdmi->pin_list, head) { + for (j = 0; j < pin->num_ports; j++) + snd_soc_dapm_disable_pin(pin->ports[j].dapm, + pin->ports[j].jack_pin); + } + + return 0; +} +EXPORT_SYMBOL_GPL(hdac_hdmi_jack_port_init); + int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, struct snd_soc_jack *jack) { diff --git a/sound/soc/codecs/hdac_hdmi.h b/sound/soc/codecs/hdac_hdmi.h index bf7edb3..dfc3a9c 100644 --- a/sound/soc/codecs/hdac_hdmi.h +++ b/sound/soc/codecs/hdac_hdmi.h @@ -4,4 +4,6 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm, struct snd_soc_jack *jack);
+int hdac_hdmi_jack_port_init(struct snd_soc_codec *codec, + struct snd_soc_dapm_context *dapm); #endif /* __HDAC_HDMI_H__ */
From: Jeeja KP jeeja.kp@intel.com
After the pcm jack is created, create and initialize the pin switch widget for each port. Pin switch is to enable/disable the pin when monitor is connected/disconnected.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/skl_rt286.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 11647b0..f5ab7b8 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -95,10 +95,6 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = { {"DMIC1 Pin", NULL, "DMIC2"}, {"DMic", NULL, "SoC DMIC"},
- {"HDMI1", NULL, "hif5-0 Output"}, - {"HDMI2", NULL, "hif6-0 Output"}, - {"HDMI3", NULL, "hif7-0 Output"}, - /* CODEC BE connections */ { "AIF1 Playback", NULL, "ssp0 Tx"}, { "ssp0 Tx", NULL, "codec0_out"}, @@ -464,10 +460,12 @@ static int skylake_card_late_probe(struct snd_soc_card *card) { struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(card); struct skl_hdmi_pcm *pcm; + struct snd_soc_codec *codec = NULL; int err, i = 0; char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + codec = pcm->codec_dai->codec; snprintf(jack_name, sizeof(jack_name), "HDMI/DP, pcm=%d Jack", pcm->device); err = snd_soc_card_jack_new(card, jack_name, @@ -485,7 +483,10 @@ static int skylake_card_late_probe(struct snd_soc_card *card) i++; }
- return 0; + if (!codec) + return -EINVAL; + + return hdac_hdmi_jack_port_init(codec, &card->dapm); }
/* skylake audio machine driver for SPT + RT286S */
From: Jeeja KP jeeja.kp@intel.com
After the pcm jack is created, create and initialize the pin switch widget for each port. Pin switch is to enable/disable the pin when monitor is connected/disconnected.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/skl_nau88l25_max98357a.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index 48f7c96..3b12bc1 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -131,9 +131,6 @@ static const struct snd_soc_dapm_route skylake_map[] = { { "MIC", NULL, "Headset Mic" }, { "DMic", NULL, "SoC DMIC" },
- {"DP1", NULL, "hif5-0 Output"}, - {"DP2", NULL, "hif6-0 Output"}, - /* CODEC BE connections */ { "HiFi Playback", NULL, "ssp0 Tx" }, { "ssp0 Tx", NULL, "codec0_out" }, @@ -609,10 +606,12 @@ static int skylake_card_late_probe(struct snd_soc_card *card) { struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(card); struct skl_hdmi_pcm *pcm; + struct snd_soc_codec *codec = NULL; int err, i = 0; char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + codec = pcm->codec_dai->codec; snprintf(jack_name, sizeof(jack_name), "HDMI/DP, pcm=%d Jack", pcm->device); err = snd_soc_card_jack_new(card, jack_name, @@ -631,7 +630,10 @@ static int skylake_card_late_probe(struct snd_soc_card *card) i++; }
- return 0; + if (!codec) + return -EINVAL; + + return hdac_hdmi_jack_port_init(codec, &card->dapm); }
/* skylake audio machine driver for SPT + NAU88L25 */
From: Jeeja KP jeeja.kp@intel.com
After the pcm jack is created, create and initialize the pin switch widget for each port. Pin switch is to enable/disable the pin when monitor is connected/disconnected.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index 5deb68f..eb7751b 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -136,9 +136,6 @@ static const struct snd_soc_dapm_route skylake_map[] = { {"MIC", NULL, "Headset Mic"}, {"DMic", NULL, "SoC DMIC"},
- {"DP1", NULL, "hif5-0 Output"}, - {"DP2", NULL, "hif6-0 Output"}, - /* CODEC BE connections */ { "Left Playback", NULL, "ssp0 Tx"}, { "Right Playback", NULL, "ssp0 Tx"}, @@ -660,10 +657,12 @@ static int skylake_card_late_probe(struct snd_soc_card *card) { struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(card); struct skl_hdmi_pcm *pcm; + struct snd_soc_codec *codec = NULL; int err, i = 0; char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + codec = pcm->codec_dai->codec; snprintf(jack_name, sizeof(jack_name), "HDMI/DP, pcm=%d Jack", pcm->device); err = snd_soc_card_jack_new(card, jack_name, @@ -682,7 +681,10 @@ static int skylake_card_late_probe(struct snd_soc_card *card) i++; }
- return 0; + if (!codec) + return -EINVAL; + + return hdac_hdmi_jack_port_init(codec, &card->dapm); }
/* skylake audio machine driver for SPT + NAU88L25 */
From: Jeeja KP jeeja.kp@intel.com
After the pcm jack is created, create and initialize the pin switch widget for each port. Pin switch is to enable/disable the pin when monitor is connected/disconnected. --- sound/soc/intel/boards/bxt_rt298.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index d5f53a6..176c080 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -459,10 +459,12 @@ static int bxt_card_late_probe(struct snd_soc_card *card) { struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(card); struct bxt_hdmi_pcm *pcm; + struct snd_soc_codec *codec = NULL; int err, i = 0; char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + codec = pcm->codec_dai->codec; snprintf(jack_name, sizeof(jack_name), "HDMI/DP, pcm=%d Jack", pcm->device); err = snd_soc_card_jack_new(card, jack_name, @@ -480,7 +482,10 @@ static int bxt_card_late_probe(struct snd_soc_card *card) i++; }
- return 0; + if (!codec) + return -EINVAL; + + return hdac_hdmi_jack_port_init(codec, &card->dapm); }
On Tue, Feb 07, 2017 at 07:09:59PM +0530, jeeja.kp@intel.com wrote:
From: Jeeja KP jeeja.kp@intel.com
After the pcm jack is created, create and initialize the pin switch widget for each port. Pin switch is to enable/disable the pin when monitor is connected/disconnected.
This has no signoffs at all, I can't do anything with it. Vinod, you acked this?
On Thu, Feb 16, 2017 at 06:56:58PM +0000, Mark Brown wrote:
On Tue, Feb 07, 2017 at 07:09:59PM +0530, jeeja.kp@intel.com wrote:
From: Jeeja KP jeeja.kp@intel.com
After the pcm jack is created, create and initialize the pin switch widget for each port. Pin switch is to enable/disable the pin when monitor is connected/disconnected.
This has no signoffs at all, I can't do anything with it. Vinod, you acked this?
Yeah sorry for the blunder :(
Not sure how that happended... Will ensure this never repeats.
Thanks
On Thu, Feb 16, 2017 at 06:56:58PM +0000, Mark Brown wrote:
On Tue, Feb 07, 2017 at 07:09:59PM +0530, jeeja.kp@intel.com wrote:
From: Jeeja KP jeeja.kp@intel.com
After the pcm jack is created, create and initialize the pin switch widget for each port. Pin switch is to enable/disable the pin when monitor is connected/disconnected.
This has no signoffs at all, I can't do anything with it. Vinod, you acked this?
Sorry, I missed it. I will take care from next time onwards. I will fix and resend this patch.
--
From: Jeeja KP jeeja.kp@intel.com
After the pcm jack is created, create and initialize the pin switch widget for each port. Pin switch is to enable/disable the pin when monitor is connected/disconnected.
Signed-off-by: Jeeja KP jeeja.kp@intel.com --- sound/soc/intel/boards/bxt_da7219_max98357a.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 18f3d0e..2cda06c 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -523,10 +523,12 @@ static int bxt_card_late_probe(struct snd_soc_card *card) { struct bxt_card_private *ctx = snd_soc_card_get_drvdata(card); struct bxt_hdmi_pcm *pcm; + struct snd_soc_codec *codec = NULL; int err, i = 0; char jack_name[NAME_SIZE];
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + codec = pcm->codec_dai->codec; snprintf(jack_name, sizeof(jack_name), "HDMI/DP, pcm=%d Jack", pcm->device); err = snd_soc_card_jack_new(card, jack_name, @@ -544,7 +546,10 @@ static int bxt_card_late_probe(struct snd_soc_card *card) i++; }
- return 0; + if (!codec) + return -EINVAL; + + return hdac_hdmi_jack_port_init(codec, &card->dapm); }
/* broxton audio machine driver for SPT + da7219 */
On Tue, Feb 07, 2017 at 07:09:44PM +0530, jeeja.kp@intel.com wrote:
From: Jeeja KP jeeja.kp@intel.com
With the patch series "ASoC: hdmi: Preparatory work to support MST audio", the design is extended from pin to port mapping to handle MST usecases.
A pin is MST capable if pipe is valid value (i.e. not -1) in the notify callback. If pipe = -1, default port is 0 else port = pipe. A MST capable pin widget is programmed by first sending a verb to select the device/port and then the actual verb is sent to program the widget.
This patch series enables MST Audio by configuring MST capable pins and extended the jack handling to report event for ports. Now the jack events are based on port connect/disconnect. The design is also extended to support mapping of multiple port to a single converter.
Now with the introduction of multiple ports with a single pin, a pin widget is created to enable/disable path based on device connection. Required machine driver changes are done to handle this change.
Also use the ASoC jack instead of snd_jack framework to creates jacks in the machine driver.
Note: This patch series has dependency on the series "ASoC: hdmi: Preparatory work to support MST audio"
Acked-by: Vinod Koul vinod.koul@intel.com
participants (4)
-
Jeeja KP
-
jeeja.kp@intel.com
-
Mark Brown
-
Vinod Koul