Merge branch 'asoc-5.3' into asoc-linus
authorMark Brown <broonie@kernel.org>
Sun, 15 Sep 2019 09:31:42 +0000 (10:31 +0100)
committerMark Brown <broonie@kernel.org>
Sun, 15 Sep 2019 09:31:42 +0000 (10:31 +0100)
1  2 
arch/arm/mach-omap1/board-ams-delta.c
sound/soc/codecs/hdac_hdmi.c
sound/soc/intel/boards/sof_rt5682.c
sound/soc/sof/intel/hda.c

@@@ -10,7 -10,6 +10,7 @@@
   */
  #include <linux/gpio/driver.h>
  #include <linux/gpio/machine.h>
 +#include <linux/gpio/consumer.h>
  #include <linux/gpio.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
@@@ -246,8 -245,8 +246,8 @@@ static struct platform_device latch2_gp
  #define LATCH2_PIN_SCARD_CMDVCC               11
  #define LATCH2_PIN_MODEM_NRESET               12
  #define LATCH2_PIN_MODEM_CODEC                13
- #define LATCH2_PIN_AUDIO_MUTE         14
- #define LATCH2_PIN_HOOKFLASH          15
+ #define LATCH2_PIN_HANDSFREE_MUTE     14
+ #define LATCH2_PIN_HANDSET_MUTE               15
  
  static struct regulator_consumer_supply modem_nreset_consumers[] = {
        REGULATOR_SUPPLY("RESET#", "serial8250.1"),
@@@ -476,6 -475,10 +476,10 @@@ static struct gpiod_lookup_table ams_de
                            "hook_switch", 0),
                GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_CODEC,
                            "modem_codec", 0),
+               GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_HANDSFREE_MUTE,
+                           "handsfree_mute", 0),
+               GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_HANDSET_MUTE,
+                           "handset_mute", 0),
                { },
        },
  };
@@@ -590,8 -593,6 +594,6 @@@ static int gpiochip_match_by_label(stru
  static struct gpiod_hog ams_delta_gpio_hogs[] = {
        GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout",
                 GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
-       GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_AUDIO_MUTE, "audio_mute",
-                GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
        {},
  };
  
@@@ -607,12 -608,12 +609,12 @@@ static void __init modem_assign_irq(str
        struct gpio_desc *gpiod;
  
        gpiod = gpiochip_request_own_desc(chip, AMS_DELTA_GPIO_PIN_MODEM_IRQ,
 -                                        "modem_irq", 0);
 +                                        "modem_irq", GPIO_ACTIVE_HIGH,
 +                                        GPIOD_IN);
        if (IS_ERR(gpiod)) {
                pr_err("%s: modem IRQ GPIO request failed (%ld)\n", __func__,
                       PTR_ERR(gpiod));
        } else {
 -              gpiod_direction_input(gpiod);
                ams_delta_modem_ports[0].irq = gpiod_to_irq(gpiod);
        }
  }
@@@ -88,8 -88,10 +88,10 @@@ struct hdac_hdmi_port 
        hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
        struct hdac_hdmi_eld eld;
        const char *jack_pin;
+       bool is_connect;
        struct snd_soc_dapm_context *dapm;
        const char *output_pin;
+       struct work_struct dapm_work;
  };
  
  struct hdac_hdmi_pcm {
@@@ -163,11 -165,7 +165,7 @@@ static void hdac_hdmi_jack_report(struc
  {
        struct hdac_device *hdev = port->pin->hdev;
  
-       if (is_connect)
-               snd_soc_dapm_enable_pin(port->dapm, port->jack_pin);
-       else
-               snd_soc_dapm_disable_pin(port->dapm, port->jack_pin);
+       port->is_connect = is_connect;
        if (is_connect) {
                /*
                 * Report Jack connect event when a device is connected
                if (pcm->jack_event > 0)
                        pcm->jack_event--;
        }
+ }
  
+ static void hdac_hdmi_port_dapm_update(struct hdac_hdmi_port *port)
+ {
+       if (port->is_connect)
+               snd_soc_dapm_enable_pin(port->dapm, port->jack_pin);
+       else
+               snd_soc_dapm_disable_pin(port->dapm, port->jack_pin);
        snd_soc_dapm_sync(port->dapm);
  }
  
+ static void hdac_hdmi_jack_dapm_work(struct work_struct *work)
+ {
+       struct hdac_hdmi_port *port;
+       port = container_of(work, struct hdac_hdmi_port, dapm_work);
+       hdac_hdmi_port_dapm_update(port);
+ }
+ static void hdac_hdmi_jack_report_sync(struct hdac_hdmi_pcm *pcm,
+               struct hdac_hdmi_port *port, bool is_connect)
+ {
+       hdac_hdmi_jack_report(pcm, port, is_connect);
+       hdac_hdmi_port_dapm_update(port);
+ }
  /* MST supported verbs */
  /*
   * Get the no devices that can be connected to a port on the Pin widget.
@@@ -539,29 -559,6 +559,29 @@@ static struct hdac_hdmi_port *hdac_hdmi
  }
  
  /*
 + * Go through all converters and ensure connection is set to
 + * the correct pin as set via kcontrols.
 + */
 +static void hdac_hdmi_verify_connect_sel_all_pins(struct hdac_device *hdev)
 +{
 +      struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
 +      struct hdac_hdmi_port *port;
 +      struct hdac_hdmi_cvt *cvt;
 +      int cvt_idx = 0;
 +
 +      list_for_each_entry(cvt, &hdmi->cvt_list, head) {
 +              port = hdac_hdmi_get_port_from_cvt(hdev, hdmi, cvt);
 +              if (port && port->pin) {
 +                      snd_hdac_codec_write(hdev, port->pin->nid, 0,
 +                                           AC_VERB_SET_CONNECT_SEL, cvt_idx);
 +                      dev_dbg(&hdev->dev, "%s: %s set connect %d -> %d\n",
 +                              __func__, cvt->name, port->pin->nid, cvt_idx);
 +              }
 +              ++cvt_idx;
 +      }
 +}
 +
 +/*
   * This tries to get a valid pin and set the HW constraints based on the
   * ELD. Even if a valid pin is not found return success so that device open
   * doesn't fail.
@@@ -821,14 -818,6 +841,14 @@@ static int hdac_hdmi_cvt_output_widget_
                                AC_VERB_SET_CHANNEL_STREAMID, pcm->stream_tag);
                snd_hdac_codec_write(hdev, cvt->nid, 0,
                                AC_VERB_SET_STREAM_FORMAT, pcm->format);
 +
 +              /*
 +               * The connection indices are shared by all converters and
 +               * may interfere with each other. Ensure correct
 +               * routing for all converters at stream start.
 +               */
 +              hdac_hdmi_verify_connect_sel_all_pins(hdev);
 +
                break;
  
        case SND_SOC_DAPM_POST_PMD:
@@@ -904,7 -893,7 +924,7 @@@ static int hdac_hdmi_set_pin_port_mux(s
                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);
+                               hdac_hdmi_jack_report_sync(pcm, port, false);
                                list_del(&p->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);
+                               hdac_hdmi_jack_report_sync(pcm, port, true);
                                mutex_unlock(&hdmi->pin_mutex);
                                return ret;
                        }
@@@ -1281,16 -1270,20 +1301,20 @@@ static void hdac_hdmi_present_sense(str
                 * report jack here. It will be done in usermode mux
                 * control select.
                 */
-               if (pcm)
+               if (pcm) {
                        hdac_hdmi_jack_report(pcm, port, false);
+                       schedule_work(&port->dapm_work);
+               }
  
                mutex_unlock(&hdmi->pin_mutex);
                return;
        }
  
        if (port->eld.monitor_present && port->eld.eld_valid) {
-               if (pcm)
+               if (pcm) {
                        hdac_hdmi_jack_report(pcm, port, true);
+                       schedule_work(&port->dapm_work);
+               }
  
                print_hex_dump_debug("ELD: ", DUMP_PREFIX_OFFSET, 16, 1,
                          port->eld.eld_buffer, port->eld.eld_size, false);
@@@ -1319,6 -1312,7 +1343,7 @@@ static int hdac_hdmi_add_ports(struct h
        for (i = 0; i < max_ports; i++) {
                ports[i].id = i;
                ports[i].pin = pin;
+               INIT_WORK(&ports[i].dapm_work, hdac_hdmi_jack_dapm_work);
        }
        pin->ports = ports;
        pin->num_ports = max_ports;
@@@ -2072,7 -2066,7 +2097,7 @@@ static int hdac_hdmi_dev_probe(struct h
                        "Failed in parse and map nid with err: %d\n", ret);
                return ret;
        }
 -      snd_hdac_refresh_widgets(hdev, true);
 +      snd_hdac_refresh_widgets(hdev);
  
        /* ASoC specific initialization */
        ret = devm_snd_soc_register_component(&hdev->dev, &hdmi_hda_codec,
        return ret;
  }
  
+ static void clear_dapm_works(struct hdac_device *hdev)
+ {
+       struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
+       struct hdac_hdmi_pin *pin;
+       int i;
+       list_for_each_entry(pin, &hdmi->pin_list, head)
+               for (i = 0; i < pin->num_ports; i++)
+                       cancel_work_sync(&pin->ports[i].dapm_work);
+ }
  static int hdac_hdmi_dev_remove(struct hdac_device *hdev)
  {
+       clear_dapm_works(hdev);
        snd_hdac_display_power(hdev->bus, hdev->addr, false);
  
        return 0;
@@@ -2103,6 -2109,8 +2140,8 @@@ static int hdac_hdmi_runtime_suspend(st
        if (!bus)
                return 0;
  
+       clear_dapm_works(hdev);
        /*
         * Power down afg.
         * codec_read is preferred over codec_write to set the power state.
@@@ -309,6 -309,7 +309,7 @@@ static const struct snd_soc_dapm_widge
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
        SND_SOC_DAPM_SPK("Spk", NULL),
+       SND_SOC_DAPM_MIC("SoC DMIC", NULL),
  };
  
  static const struct snd_soc_dapm_route sof_map[] = {
        /* other jacks */
        { "IN1P", NULL, "Headset Mic" },
  
+       /* digital mics */
+       {"DMic", NULL, "SoC DMIC"},
  };
  
  static const struct snd_soc_dapm_route speaker_map[] = {
@@@ -551,7 -555,7 +555,7 @@@ static int sof_audio_probe(struct platf
        int dmic_be_num, hdmi_num;
        int ret, ssp_amp, ssp_codec;
  
 -      ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC);
 +      ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
  
@@@ -34,9 -34,6 +34,9 @@@
  /* platform specific devices */
  #include "shim.h"
  
 +#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
 +#define IS_CNL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9dc8)
 +
  /*
   * Debug
   */
@@@ -248,11 -245,6 +248,11 @@@ static int hda_init(struct snd_sof_dev 
        ext_ops = snd_soc_hdac_hda_get_ops();
  #endif
        sof_hda_bus_init(bus, &pci->dev, ext_ops);
 +
 +      /* Workaround for a communication error on CFL (bko#199007) and CNL */
 +      if (IS_CFL(pci) || IS_CNL(pci))
 +              bus->polling_mode = 1;
 +
        bus->use_posbuf = 1;
        bus->bdl_pos_adj = 0;
  
@@@ -329,10 -321,23 +329,23 @@@ static int hda_init_caps(struct snd_sof
        if (bus->ppcap)
                dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n");
  
+ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+       /* init i915 and HDMI codecs */
+       ret = hda_codec_i915_init(sdev);
+       if (ret < 0) {
+               dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n");
+               return ret;
+       }
+ #endif
+       /* Init HDA controller after i915 init */
        ret = hda_dsp_ctrl_init_chip(sdev, true);
        if (ret < 0) {
                dev_err(bus->dev, "error: init chip failed with ret: %d\n",
                        ret);
+ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+               hda_codec_i915_exit(sdev);
+ #endif
                return ret;
        }
  
        if (bus->mlcap)
                snd_hdac_ext_bus_get_ml_capabilities(bus);
  
-       /* init i915 and HDMI codecs */
-       ret = hda_codec_i915_init(sdev);
-       if (ret < 0) {
-               dev_err(sdev->dev, "error: no HDMI audio devices found\n");
-               return ret;
-       }
        /* codec detection */
        if (!bus->codec_mask) {
                dev_info(bus->dev, "no hda codecs found!\n");