]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'sound-fix-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Mar 2017 17:59:21 +0000 (09:59 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Mar 2017 17:59:21 +0000 (09:59 -0800)
Pull sound fixes from Takashi Iwai:
 "A few last-minute fixes for rc1:

   - ALSA core timer and sequencer fixes for bugs spotted by syzkaller

   - a couple of trivial HD-audio fixups

   - additional PCI / codec IDs for Intel Geminilake

   - fixes for CT-XFi DMA mask bugs"

* tag 'sound-fix-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: seq: Fix link corruption by event error handling
  ALSA: hda - Add subwoofer support for Dell Inspiron 17 7000 Gaming
  ALSA: ctxfi: Fallback DMA mask to 32bit
  ALSA: timer: Reject user params with too small ticks
  ALSA: hda: Add Geminilake HDMI codec ID
  ALSA: hda - Fix micmute hotkey problem for a lenovo AIO machine
  ALSA: hda - Add Geminilake PCI ID

1  2 
sound/pci/hda/patch_hdmi.c

index fd5efa72a68bd3044b51572cdf9988bce20eb3ff,c51e3218e33e30132c9b93cc77899415abd31026..1461ef8eb7495d1d0f46ff0d6b5a15ece3c1a1da
@@@ -76,7 -76,6 +76,7 @@@ struct hdmi_spec_per_cvt 
  
  struct hdmi_spec_per_pin {
        hda_nid_t pin_nid;
 +      int dev_id;
        /* pin idx, different device entries on the same pin use the same idx */
        int pin_nid_idx;
        int num_mux_nids;
@@@ -131,23 -130,7 +131,23 @@@ struct hdmi_spec 
        struct snd_array cvts; /* struct hdmi_spec_per_cvt */
        hda_nid_t cvt_nids[4]; /* only for haswell fix */
  
 +      /*
 +       * num_pins is the number of virtual pins
 +       * for example, there are 3 pins, and each pin
 +       * has 4 device entries, then the num_pins is 12
 +       */
        int num_pins;
 +      /*
 +       * num_nids is the number of real pins
 +       * In the above example, num_nids is 3
 +       */
 +      int num_nids;
 +      /*
 +       * dev_num is the number of device entries
 +       * on each pin.
 +       * In the above example, dev_num is 4
 +       */
 +      int dev_num;
        struct snd_array pins; /* struct hdmi_spec_per_pin */
        struct hdmi_pcm pcm_rec[16];
        struct mutex pcm_lock;
@@@ -234,26 -217,14 +234,26 @@@ union audio_infoframe 
  /* obtain hda_pcm object assigned to idx */
  #define get_pcm_rec(spec, idx)        (get_hdmi_pcm(spec, idx)->pcm)
  
 -static int pin_nid_to_pin_index(struct hda_codec *codec, hda_nid_t pin_nid)
 +static int pin_id_to_pin_index(struct hda_codec *codec,
 +                             hda_nid_t pin_nid, int dev_id)
  {
        struct hdmi_spec *spec = codec->spec;
        int pin_idx;
 +      struct hdmi_spec_per_pin *per_pin;
  
 -      for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
 -              if (get_pin(spec, pin_idx)->pin_nid == pin_nid)
 +      /*
 +       * (dev_id == -1) means it is NON-MST pin
 +       * return the first virtual pin on this port
 +       */
 +      if (dev_id == -1)
 +              dev_id = 0;
 +
 +      for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
 +              per_pin = get_pin(spec, pin_idx);
 +              if ((per_pin->pin_nid == pin_nid) &&
 +                      (per_pin->dev_id == dev_id))
                        return pin_idx;
 +      }
  
        codec_warn(codec, "HDMI: pin nid %d not registered\n", pin_nid);
        return -EINVAL;
@@@ -753,11 -724,10 +753,11 @@@ static void hdmi_setup_audio_infoframe(
  
  static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
  
 -static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid)
 +static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid,
 +                                    int dev_id)
  {
        struct hdmi_spec *spec = codec->spec;
 -      int pin_idx = pin_nid_to_pin_index(codec, nid);
 +      int pin_idx = pin_id_to_pin_index(codec, nid, dev_id);
  
        if (pin_idx < 0)
                return;
  static void jack_callback(struct hda_codec *codec,
                          struct hda_jack_callback *jack)
  {
 -      check_presence_and_report(codec, jack->nid);
 +      /* hda_jack don't support DP MST */
 +      check_presence_and_report(codec, jack->nid, 0);
  }
  
  static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
        struct hda_jack_tbl *jack;
        int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
  
 +      /*
 +       * assume DP MST uses dyn_pcm_assign and acomp and
 +       * never comes here
 +       * if DP MST supports unsol event, below code need
 +       * consider dev_entry
 +       */
        jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
        if (!jack)
                return;
                codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
                !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
  
 -      check_presence_and_report(codec, jack->nid);
 +      /* hda_jack don't support DP MST */
 +      check_presence_and_report(codec, jack->nid, 0);
  }
  
  static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@@ -1008,60 -970,28 +1008,60 @@@ static int intel_cvt_id_to_mux_idx(stru
   * by any other pins.
   */
  static void intel_not_share_assigned_cvt(struct hda_codec *codec,
 -                      hda_nid_t pin_nid, int mux_idx)
 +                                       hda_nid_t pin_nid,
 +                                       int dev_id, int mux_idx)
  {
        struct hdmi_spec *spec = codec->spec;
        hda_nid_t nid;
        int cvt_idx, curr;
        struct hdmi_spec_per_cvt *per_cvt;
 +      struct hdmi_spec_per_pin *per_pin;
 +      int pin_idx;
 +
 +      /* configure the pins connections */
 +      for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
 +              int dev_id_saved;
 +              int dev_num;
  
 -      /* configure all pins, including "no physical connection" ones */
 -      for_each_hda_codec_node(nid, codec) {
 -              unsigned int wid_caps = get_wcaps(codec, nid);
 -              unsigned int wid_type = get_wcaps_type(wid_caps);
 +              per_pin = get_pin(spec, pin_idx);
 +              /*
 +               * pin not connected to monitor
 +               * no need to operate on it
 +               */
 +              if (!per_pin->pcm)
 +                      continue;
  
 -              if (wid_type != AC_WID_PIN)
 +              if ((per_pin->pin_nid == pin_nid) &&
 +                      (per_pin->dev_id == dev_id))
                        continue;
  
 -              if (nid == pin_nid)
 +              /*
 +               * if per_pin->dev_id >= dev_num,
 +               * snd_hda_get_dev_select() will fail,
 +               * and the following operation is unpredictable.
 +               * So skip this situation.
 +               */
 +              dev_num = snd_hda_get_num_devices(codec, per_pin->pin_nid) + 1;
 +              if (per_pin->dev_id >= dev_num)
                        continue;
  
 +              nid = per_pin->pin_nid;
 +
 +              /*
 +               * Calling this function should not impact
 +               * on the device entry selection
 +               * So let's save the dev id for each pin,
 +               * and restore it when return
 +               */
 +              dev_id_saved = snd_hda_get_dev_select(codec, nid);
 +              snd_hda_set_dev_select(codec, nid, per_pin->dev_id);
                curr = snd_hda_codec_read(codec, nid, 0,
                                          AC_VERB_GET_CONNECT_SEL, 0);
 -              if (curr != mux_idx)
 +              if (curr != mux_idx) {
 +                      snd_hda_set_dev_select(codec, nid, dev_id_saved);
                        continue;
 +              }
 +
  
                /* choose an unassigned converter. The conveters in the
                 * connection list are in the same order as in the codec.
                                break;
                        }
                }
 +              snd_hda_set_dev_select(codec, nid, dev_id_saved);
        }
  }
  
  /* A wrapper of intel_not_share_asigned_cvt() */
  static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec,
 -                      hda_nid_t pin_nid, hda_nid_t cvt_nid)
 +                      hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid)
  {
        int mux_idx;
        struct hdmi_spec *spec = codec->spec;
         */
        mux_idx = intel_cvt_id_to_mux_idx(spec, cvt_nid);
        if (mux_idx >= 0)
 -              intel_not_share_assigned_cvt(codec, pin_nid, mux_idx);
 +              intel_not_share_assigned_cvt(codec, pin_nid, dev_id, mux_idx);
  }
  
  /* skeleton caller of pin_cvt_fixup ops */
@@@ -1211,7 -1140,6 +1211,7 @@@ static int hdmi_pcm_open(struct hda_pcm
        per_pin->cvt_nid = per_cvt->cvt_nid;
        hinfo->nid = per_cvt->cvt_nid;
  
 +      snd_hda_set_dev_select(codec, per_pin->pin_nid, per_pin->dev_id);
        snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
                            AC_VERB_SET_CONNECT_SEL,
                            per_pin->mux_idx);
@@@ -1270,7 -1198,6 +1270,7 @@@ static int hdmi_read_pin_conn(struct hd
                return -EINVAL;
        }
  
 +      /* all the device entries on the same pin have the same conn list */
        per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid,
                                                        per_pin->mux_nids,
                                                        HDA_MAX_CONNECTIONS);
@@@ -1288,13 -1215,13 +1288,13 @@@ static int hdmi_find_pcm_slot(struct hd
                return per_pin->pin_nid_idx;
  
        /* have a second try; check the "reserved area" over num_pins */
 -      for (i = spec->num_pins; i < spec->pcm_used; i++) {
 +      for (i = spec->num_nids; i < spec->pcm_used; i++) {
                if (!test_bit(i, &spec->pcm_bitmap))
                        return i;
        }
  
        /* the last try; check the empty slots in pins */
 -      for (i = 0; i < spec->num_pins; i++) {
 +      for (i = 0; i < spec->num_nids; i++) {
                if (!test_bit(i, &spec->pcm_bitmap))
                        return i;
        }
@@@ -1369,13 -1296,10 +1369,13 @@@ static void hdmi_pcm_setup_pin(struct h
        per_pin->cvt_nid = hinfo->nid;
  
        mux_idx = hdmi_get_pin_cvt_mux(spec, per_pin, hinfo->nid);
 -      if (mux_idx < per_pin->num_mux_nids)
 +      if (mux_idx < per_pin->num_mux_nids) {
 +              snd_hda_set_dev_select(codec, per_pin->pin_nid,
 +                                 per_pin->dev_id);
                snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
                                AC_VERB_SET_CONNECT_SEL,
                                mux_idx);
 +      }
        snd_hda_spdif_ctls_assign(codec, per_pin->pcm_idx, hinfo->nid);
  
        non_pcm = check_non_pcm_per_cvt(codec, hinfo->nid);
@@@ -1543,11 -1467,6 +1543,11 @@@ static struct snd_jack *pin_idx_to_jack
        if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign)
                jack = spec->pcm_rec[per_pin->pcm_idx].jack;
        else if (!spec->dyn_pcm_assign) {
 +              /*
 +               * jack tbl doesn't support DP MST
 +               * DP MST will use dyn_pcm_assign,
 +               * so DP MST will never come here
 +               */
                jack_tbl = snd_hda_jack_tbl_get(codec, per_pin->pin_nid);
                if (jack_tbl)
                        jack = jack_tbl->jack;
@@@ -1566,9 -1485,9 +1566,9 @@@ static void sync_eld_via_acomp(struct h
  
        mutex_lock(&per_pin->lock);
        eld->monitor_present = false;
 -      size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid, -1,
 -                                    &eld->monitor_present, eld->eld_buffer,
 -                                    ELD_MAX_SIZE);
 +      size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid,
 +                                    per_pin->dev_id, &eld->monitor_present,
 +                                    eld->eld_buffer, ELD_MAX_SIZE);
        if (size > 0) {
                size = min(size, ELD_MAX_SIZE);
                if (snd_hdmi_parse_eld(codec, &eld->info,
@@@ -1646,81 -1565,38 +1646,81 @@@ static int hdmi_add_pin(struct hda_code
        int pin_idx;
        struct hdmi_spec_per_pin *per_pin;
        int err;
 +      int dev_num, i;
  
        caps = snd_hda_query_pin_caps(codec, pin_nid);
        if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
                return 0;
  
 +      /*
 +       * For DP MST audio, Configuration Default is the same for
 +       * all device entries on the same pin
 +       */
        config = snd_hda_codec_get_pincfg(codec, pin_nid);
        if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
                return 0;
  
 -      if (is_haswell_plus(codec))
 -              intel_haswell_fixup_connect_list(codec, pin_nid);
 -
 -      pin_idx = spec->num_pins;
 -      per_pin = snd_array_new(&spec->pins);
 -      if (!per_pin)
 -              return -ENOMEM;
 -
 -      per_pin->pin_nid = pin_nid;
 -      per_pin->non_pcm = false;
 -      if (spec->dyn_pcm_assign)
 -              per_pin->pcm_idx = -1;
 -      else {
 -              per_pin->pcm = get_hdmi_pcm(spec, pin_idx);
 -              per_pin->pcm_idx = pin_idx;
 +      /*
 +       * To simplify the implementation, malloc all
 +       * the virtual pins in the initialization statically
 +       */
 +      if (is_haswell_plus(codec)) {
 +              /*
 +               * On Intel platforms, device entries number is
 +               * changed dynamically. If there is a DP MST
 +               * hub connected, the device entries number is 3.
 +               * Otherwise, it is 1.
 +               * Here we manually set dev_num to 3, so that
 +               * we can initialize all the device entries when
 +               * bootup statically.
 +               */
 +              dev_num = 3;
 +              spec->dev_num = 3;
 +      } else if (spec->dyn_pcm_assign && codec->dp_mst) {
 +              dev_num = snd_hda_get_num_devices(codec, pin_nid) + 1;
 +              /*
 +               * spec->dev_num is the maxinum number of device entries
 +               * among all the pins
 +               */
 +              spec->dev_num = (spec->dev_num > dev_num) ?
 +                      spec->dev_num : dev_num;
 +      } else {
 +              /*
 +               * If the platform doesn't support DP MST,
 +               * manually set dev_num to 1. This means
 +               * the pin has only one device entry.
 +               */
 +              dev_num = 1;
 +              spec->dev_num = 1;
        }
 -      per_pin->pin_nid_idx = pin_idx;
  
 -      err = hdmi_read_pin_conn(codec, pin_idx);
 -      if (err < 0)
 -              return err;
 +      for (i = 0; i < dev_num; i++) {
 +              pin_idx = spec->num_pins;
 +              per_pin = snd_array_new(&spec->pins);
  
 -      spec->num_pins++;
 +              if (!per_pin)
 +                      return -ENOMEM;
 +
 +              if (spec->dyn_pcm_assign) {
 +                      per_pin->pcm = NULL;
 +                      per_pin->pcm_idx = -1;
 +              } else {
 +                      per_pin->pcm = get_hdmi_pcm(spec, pin_idx);
 +                      per_pin->pcm_idx = pin_idx;
 +              }
 +              per_pin->pin_nid = pin_nid;
 +              per_pin->pin_nid_idx = spec->num_nids;
 +              per_pin->dev_id = i;
 +              per_pin->non_pcm = false;
 +              snd_hda_set_dev_select(codec, pin_nid, i);
 +              if (is_haswell_plus(codec))
 +                      intel_haswell_fixup_connect_list(codec, pin_nid);
 +              err = hdmi_read_pin_conn(codec, pin_idx);
 +              if (err < 0)
 +                      return err;
 +              spec->num_pins++;
 +      }
 +      spec->num_nids++;
  
        return 0;
  }
@@@ -1868,7 -1744,7 +1868,7 @@@ static int generic_hdmi_playback_pcm_pr
        /* Call sync_audio_rate to set the N/CTS/M manually if necessary */
        /* Todo: add DP1.2 MST audio support later */
        if (codec_has_acomp(codec))
 -              snd_hdac_sync_audio_rate(&codec->core, pin_nid, -1,
 +              snd_hdac_sync_audio_rate(&codec->core, pin_nid, per_pin->dev_id,
                                         runtime->rate);
  
        non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
                                    pinctl | PIN_OUT);
        }
  
 +      /* snd_hda_set_dev_select() has been called before */
        err = spec->ops.setup_stream(codec, cvt_nid, pin_nid,
                                 stream_tag, format);
        mutex_unlock(&spec->pcm_lock);
@@@ -2022,23 -1897,17 +2022,23 @@@ static bool is_hdmi_pcm_attached(struc
  static int generic_hdmi_build_pcms(struct hda_codec *codec)
  {
        struct hdmi_spec *spec = codec->spec;
 -      int pin_idx;
 +      int idx;
  
 -      for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
 +      /*
 +       * for non-mst mode, pcm number is the same as before
 +       * for DP MST mode, pcm number is (nid number + dev_num - 1)
 +       *  dev_num is the device entry number in a pin
 +       *
 +       */
 +      for (idx = 0; idx < spec->num_nids + spec->dev_num - 1; idx++) {
                struct hda_pcm *info;
                struct hda_pcm_stream *pstr;
  
 -              info = snd_hda_codec_pcm_new(codec, "HDMI %d", pin_idx);
 +              info = snd_hda_codec_pcm_new(codec, "HDMI %d", idx);
                if (!info)
                        return -ENOMEM;
  
 -              spec->pcm_rec[pin_idx].pcm = info;
 +              spec->pcm_rec[idx].pcm = info;
                spec->pcm_used++;
                info->pcm_type = HDA_PCM_TYPE_HDMI;
                info->own_chmap = true;
                pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
                pstr->substreams = 1;
                pstr->ops = generic_ops;
 +              /* pcm number is less than 16 */
 +              if (spec->pcm_used >= 16)
 +                      break;
                /* other pstr fields are set in open */
        }
  
@@@ -2204,9 -2070,7 +2204,9 @@@ static int generic_hdmi_init(struct hda
        for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
                struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
                hda_nid_t pin_nid = per_pin->pin_nid;
 +              int dev_id = per_pin->dev_id;
  
 +              snd_hda_set_dev_select(codec, pin_nid, dev_id);
                hdmi_init_pin(codec, pin_nid);
                if (!codec_has_acomp(codec))
                        snd_hda_jack_detect_enable_callback(codec, pin_nid,
@@@ -2314,7 -2178,6 +2314,7 @@@ static int alloc_generic_hdmi(struct hd
                return -ENOMEM;
  
        spec->ops = generic_standard_hdmi_ops;
 +      spec->dev_num = 1;      /* initialize to 1 */
        mutex_init(&spec->pcm_lock);
        snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);
  
@@@ -2432,7 -2295,6 +2432,7 @@@ static void intel_pin_eld_notify(void *
  {
        struct hda_codec *codec = audio_ptr;
        int pin_nid;
 +      int dev_id = pipe;
  
        /* we assume only from port-B to port-D */
        if (port < 1 || port > 3)
                return;
  
        snd_hdac_i915_set_bclk(&codec->bus->core);
 -      check_presence_and_report(codec, pin_nid);
 +      check_presence_and_report(codec, pin_nid, dev_id);
  }
  
  /* register i915 component pin_eld_notify callback */
@@@ -2492,13 -2354,11 +2492,13 @@@ static void i915_pin_cvt_fixup(struct h
                               hda_nid_t cvt_nid)
  {
        if (per_pin) {
 +              snd_hda_set_dev_select(codec, per_pin->pin_nid,
 +                             per_pin->dev_id);
                intel_verify_pin_cvt_connect(codec, per_pin);
                intel_not_share_assigned_cvt(codec, per_pin->pin_nid,
 -                                           per_pin->mux_idx);
 +                                   per_pin->dev_id, per_pin->mux_idx);
        } else {
 -              intel_not_share_assigned_cvt_nid(codec, 0, cvt_nid);
 +              intel_not_share_assigned_cvt_nid(codec, 0, 0, cvt_nid);
        }
  }
  
@@@ -2518,8 -2378,6 +2518,8 @@@ static int patch_i915_hsw_hdmi(struct h
        if (err < 0)
                return err;
        spec = codec->spec;
 +      codec->dp_mst = true;
 +      spec->dyn_pcm_assign = true;
  
        intel_haswell_enable_all_pins(codec, true);
        intel_haswell_fixup_enable_dp12(codec);
                codec->core.link_power_control = 1;
  
        codec->patch_ops.set_power_state = haswell_set_power_state;
 -      codec->dp_mst = true;
        codec->depop_delay = 0;
        codec->auto_runtime_pm = 1;
  
@@@ -3800,6 -3659,7 +3800,7 @@@ HDA_CODEC_ENTRY(0x80862808, "Broadwell 
  HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI",   patch_i915_hsw_hdmi),
  HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI",   patch_i915_hsw_hdmi),
  HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI",  patch_i915_hsw_hdmi),
+ HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI",        patch_i915_hsw_hdmi),
  HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI",        patch_generic_hdmi),
  HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI",       patch_i915_byt_hdmi),
  HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI",  patch_i915_byt_hdmi),