Print this page
10619 audiohd ignores digital output pins such as HDMI/DP

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/audio/drv/audiohd/audiohd.c
          +++ new/usr/src/uts/common/io/audio/drv/audiohd/audiohd.c
↓ open down ↓ 18 lines elided ↑ open up ↑
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   */
  24   24  
  25   25  #include <sys/audio/audio_driver.h>
  26   26  #include <sys/note.h>
  27   27  #include <sys/beep.h>
  28   28  #include <sys/pci.h>
       29 +#include <sys/stddef.h>
       30 +#include <sys/sysmacros.h>
  29   31  #include "audiohd.h"
  30   32  
  31   33  #define DRVNAME                 "audiohd"
  32   34  
  33   35  /*
  34   36   * Module linkage routines for the kernel
  35   37   */
  36   38  static int audiohd_attach(dev_info_t *, ddi_attach_cmd_t);
  37   39  static int audiohd_detach(dev_info_t *, ddi_detach_cmd_t);
  38   40  static int audiohd_quiesce(dev_info_t *);
↓ open down ↓ 38 lines elided ↑ open up ↑
  77   79  static void audiohd_beep_off(void *);
  78   80  static void audiohd_beep_freq(void *, int);
  79   81  static wid_t audiohd_find_beep(hda_codec_t *, wid_t, int);
  80   82  static void audiohd_build_beep_path(hda_codec_t *);
  81   83  static void audiohd_build_beep_amp(hda_codec_t *);
  82   84  static void  audiohd_finish_beep_path(hda_codec_t *);
  83   85  static void audiohd_do_set_beep_volume(audiohd_state_t *,
  84   86      audiohd_path_t *, uint64_t);
  85   87  static void audiohd_set_beep_volume(audiohd_state_t *);
  86   88  static int audiohd_set_beep(void *, uint64_t);
       89 +static void audiohd_setup_hdmi_dp(audiohd_state_t *, uint8_t, uint8_t,
       90 +    boolean_t);
       91 +static audiohd_eld_t *audiohd_get_eld(audiohd_state_t *, uint8_t, uint8_t);
  87   92  static void audiohd_pin_sense(audiohd_state_t *, uint32_t, uint32_t);
  88   93  
  89   94  static  int     audiohd_beep;
  90   95  static  int     audiohd_beep_divider;
  91   96  static  int     audiohd_beep_vol = 1;
  92   97  
  93   98  /* Warlock annotation */
  94   99  _NOTE(SCHEME_PROTECTS_DATA("unshared data", audiohd_beep))
  95  100  _NOTE(SCHEME_PROTECTS_DATA("unshared data", audiohd_beep_divider))
  96  101  _NOTE(SCHEME_PROTECTS_DATA("unshared data", audiohd_beep_vol))
↓ open down ↓ 229 lines elided ↑ open up ↑
 326  331  
 327  332          mutex_init(&statep->hda_mutex, NULL, MUTEX_DRIVER, 0);
 328  333          mutex_enter(&statep->hda_mutex);
 329  334  
 330  335          /* interrupt cookie and initialize mutex */
 331  336          if (audiohd_init_state(statep, dip) != DDI_SUCCESS) {
 332  337                  audio_dev_warn(NULL, "audiohd_init_state failed");
 333  338                  goto error;
 334  339          }
 335  340  
 336      -        /* Set PCI command register to enable bus master and memeory I/O */
      341 +        /* Set PCI command register to enable bus master and memory I/O */
 337  342          if (audiohd_init_pci(statep, &hda_dev_accattr) != DDI_SUCCESS) {
 338  343                  audio_dev_warn(statep->adev,
 339  344                      "couldn't init pci regs");
 340  345                  goto error;
 341  346          }
 342  347  
 343  348          audiohd_set_chipset_info(statep);
 344  349  
 345  350          if (audiohd_init_controller(statep) != DDI_SUCCESS) {
 346  351                  audio_dev_warn(statep->adev,
↓ open down ↓ 228 lines elided ↑ open up ↑
 575  580          audiohd_pin_color_t             color;
 576  581  
 577  582          audiohd_state_t         *statep = path->statep;
 578  583          hda_codec_t             *codec = path->codec;
 579  584  
 580  585          /* enable SPDIF output */
 581  586          for (i = 0; i < path->pin_nums; i++) {
 582  587                  wid = path->pin_wid[i];
 583  588                  widget = codec->widget[wid];
 584  589                  pin = (audiohd_pin_t *)widget->priv;
 585      -                if (pin->device == DTYPE_SPDIF_OUT) {
      590 +                if (pin->device == DTYPE_SPDIF_OUT ||
      591 +                    pin->device == DTYPE_DIGIT_OUT) {
 586  592                          ctrl = audioha_codec_verb_get(
 587  593                              statep,
 588  594                              codec->index,
 589  595                              path->adda_wid,
 590  596                              AUDIOHDC_VERB_GET_SPDIF_CTL,
 591  597                              0);
 592  598                          ctrl |= AUDIOHD_SPDIF_ON;
 593  599                          ctrl8 = ctrl &
 594  600                              AUDIOHD_SPDIF_MASK;
 595  601                          (void) audioha_codec_verb_get(
↓ open down ↓ 63 lines elided ↑ open up ↑
 659  665                      AUDIOHD_PLAY_TAG_OFF |
 660  666                      nchann);
 661  667                  (void) audioha_codec_4bit_verb_get(
 662  668                      statep,
 663  669                      codec->index,
 664  670                      path->adda_wid,
 665  671                      AUDIOHDC_VERB_SET_CONV_FMT,
 666  672                      statep->port[PORT_DAC]->format << 4 |
 667  673                      statep->pchan - 1);
 668  674          }
      675 +
      676 +        /* Setup HDMI/DP output pin */
      677 +        if (pin->device == DTYPE_DIGIT_OUT) {
      678 +                pin->eld = audiohd_get_eld(statep, codec->index, pin->wid);
      679 +                if (pin->eld != NULL &&
      680 +                    (pin->eld->eld_conn_type & 0x3) != 0)
      681 +                        audiohd_setup_hdmi_dp(statep, codec->index, pin->wid,
      682 +                            pin->eld->eld_conn_type == AUDIOHD_ELD_CONN_HDMI);
      683 +        }
 669  684  }
      685 +
 670  686  static void
 671  687  audiohd_init_record_path(audiohd_path_t *path)
 672  688  {
 673  689          audiohd_state_t         *statep = path->statep;
 674  690          hda_codec_t             *codec = path->codec;
 675  691          int                     i;
 676  692          wid_t                   wid;
 677  693          audiohd_pin_t           *pin;
 678  694          audiohd_widget_t        *widget;
 679  695  
↓ open down ↓ 1455 lines elided ↑ open up ↑
2135 2151           */
2136 2152          cmdreg = pci_config_get16(statep->hda_pci_handle, PCI_CONF_COMM);
2137 2153          pci_config_put16(statep->hda_pci_handle, PCI_CONF_COMM,
2138 2154              cmdreg | PCI_COMM_MAE | PCI_COMM_ME);
2139 2155  
2140 2156          vid = pci_config_get16(statep->hda_pci_handle, PCI_CONF_VENID);
2141 2157          switch (vid) {
2142 2158          case AUDIOHD_VID_INTEL:
2143 2159                  /*
2144 2160                   * Currently, Intel (G)MCH and ICHx chipsets support PCI
2145      -                 * Express QoS. It implemenets two VCs(virtual channels)
     2161 +                 * Express QoS. It implements two VCs (virtual channels)
2146 2162                   * and allows OS software to map 8 traffic classes to the
2147 2163                   * two VCs. Some BIOSes initialize HD audio hardware to
2148 2164                   * use TC7 (traffic class 7) and to map TC7 to VC1 as Intel
2149 2165                   * recommended. However, solaris doesn't support PCI express
2150 2166                   * QoS yet. As a result, this driver can not work for those
2151 2167                   * hardware without touching PCI express control registers.
2152 2168                   * Here, we set TCSEL to 0 so as to use TC0/VC0 (VC0 is
2153 2169                   * always enabled and TC0 is always mapped to VC0) for all
2154 2170                   * Intel HD audio controllers.
2155 2171                   */
↓ open down ↓ 561 lines elided ↑ open up ↑
2717 2733                  pin->vrefvalue = 0x1;
2718 2734  
2719 2735          pin->seq = config & AUDIOHD_PIN_SEQ_MASK;
2720 2736          pin->assoc = (config & AUDIOHD_PIN_ASO_MASK) >> AUDIOHD_PIN_ASO_OFF;
2721 2737          pin->device = (config & AUDIOHD_PIN_DEV_MASK) >> AUDIOHD_PIN_DEV_OFF;
2722 2738  
2723 2739          /* enable the unsolicited response of the pin */
2724 2740          if ((widget->widget_cap & AUDIOHD_URCAP_MASK) &&
2725 2741              (pin->cap & AUDIOHD_DTCCAP_MASK) &&
2726 2742              ((pin->device == DTYPE_LINEOUT) ||
     2743 +            (pin->device == DTYPE_DIGIT_OUT) ||
2727 2744              (pin->device == DTYPE_SPDIF_OUT) ||
2728 2745              (pin->device == DTYPE_HP_OUT) ||
2729 2746              (pin->device == DTYPE_MIC_IN))) {
2730 2747                          urctrl = (uint8_t)(1 << (AUDIOHD_UR_ENABLE_OFF - 1));
2731 2748                          urctrl |= (wid & AUDIOHD_UR_TAG_MASK);
2732 2749                          (void) audioha_codec_verb_get(statep, caddr,
2733 2750                              wid, AUDIOHDC_VERB_SET_UNS_ENABLE, urctrl);
2734 2751          }
2735 2752          /* accommodate all the pins in a link list sorted by assoc and seq */
2736 2753          if (codec->first_pin == NULL) {
↓ open down ↓ 496 lines elided ↑ open up ↑
3233 3250          statep = codec->statep;
3234 3251  
3235 3252          for (pin = codec->first_pin; pin; pin = pin->next) {
3236 3253                  if ((pin->cap & AUDIOHD_PIN_CAP_MASK) == 0)
3237 3254                          continue;
3238 3255                  if ((pin->config & AUDIOHD_PIN_CONF_MASK) ==
3239 3256                      AUDIOHD_PIN_NO_CONN)
3240 3257                          continue;
3241 3258                  if ((pin->device != DTYPE_LINEOUT) &&
3242 3259                      (pin->device != DTYPE_SPEAKER) &&
     3260 +                    (pin->device != DTYPE_DIGIT_OUT) &&
3243 3261                      (pin->device != DTYPE_SPDIF_OUT) &&
3244 3262                      (pin->device != DTYPE_HP_OUT))
3245 3263                          continue;
3246 3264                  if (pin->finish)
3247 3265                          continue;
3248 3266                  widget = codec->widget[pin->wid];
3249 3267  
3250 3268                  widget->inamp_cap = 0;
3251 3269                  for (i = 0; i < widget->nconns; i++) {
3252 3270                          /*
↓ open down ↓ 494 lines elided ↑ open up ↑
3747 3765                  widget = codec->widget[wid];
3748 3766  
3749 3767                  /* check if it is an ADC widget */
3750 3768                  if (widget == NULL || widget->type != WTYPE_AUDIO_IN)
3751 3769                          continue;
3752 3770  
3753 3771                  if (path == NULL)
3754 3772                          path = kmem_zalloc(sizeof (audiohd_path_t),
3755 3773                              KM_SLEEP);
3756 3774                  else
3757      -                        bzero(path, sizeof (audiohd_port_t));
     3775 +                        bzero(path, sizeof (audiohd_path_t));
3758 3776  
3759 3777                  path->adda_wid = wid;
3760 3778  
3761 3779                  /*
3762 3780                   * Is there any ADC widget which has more than one input ??
3763 3781                   * I don't believe. Anyway, we carefully deal with this. But
3764 3782                   * if hardware vendors embed a selector in a ADC, we just use
3765 3783                   * the first available input, which has connection to input pin
3766 3784                   * widget. Because selector cannot perform mixer functionality,
3767 3785                   * and we just permit one selector or mixer in a recording path,
↓ open down ↓ 778 lines elided ↑ open up ↑
4546 4564          statep = codec->statep;
4547 4565  
4548 4566          for (pin = codec->first_pin; pin; pin = pin->next) {
4549 4567                  if ((pin->cap & AUDIOHD_PIN_CAP_MASK) == 0)
4550 4568                          continue;
4551 4569                  if ((pin->config & AUDIOHD_PIN_CONF_MASK) ==
4552 4570                      AUDIOHD_PIN_NO_CONN)
4553 4571                          continue;
4554 4572                  if ((pin->device != DTYPE_LINEOUT) &&
4555 4573                      (pin->device != DTYPE_SPEAKER) &&
     4574 +                    (pin->device != DTYPE_DIGIT_OUT) &&
4556 4575                      (pin->device != DTYPE_SPDIF_OUT) &&
4557 4576                      (pin->device != DTYPE_HP_OUT))
4558 4577                          continue;
4559 4578                  widget = codec->widget[pin->wid];
4560 4579  
4561 4580                  widget->inamp_cap = 0;
4562 4581                  for (i = 0; i < widget->nconns; i++) {
4563 4582                          /*
4564 4583                           * If a beep found, the return value is the wid of the
4565 4584                           * widget on the path, or the return value is
↓ open down ↓ 252 lines elided ↑ open up ↑
4818 4837                          return (DDI_FAILURE);
4819 4838  
4820 4839                  switch (pin->device) {
4821 4840                  case DTYPE_LINE_IN:
4822 4841                          /* Connection between line-in and output pins */
4823 4842                          path->pin_wid[path->pin_nums++] = wid;
4824 4843                          break;
4825 4844                  case DTYPE_LINEOUT:
4826 4845                  case DTYPE_HP_OUT:
4827 4846                  case DTYPE_SPDIF_OUT:
     4847 +                case DTYPE_DIGIT_OUT:
4828 4848                          widget->path_flags |= AUDIOHD_PATH_LOOPBACK;
4829 4849                          widget->in_weight++;
4830 4850                          pin->adc_wid = path->adda_wid;
4831 4851                          path->pin_wid[path->pin_nums++] = wid;
4832 4852                          retval = (DDI_SUCCESS);
4833 4853                          break;
4834 4854                  default:
4835 4855                          break;
4836 4856                  }
4837 4857                  break;
↓ open down ↓ 48 lines elided ↑ open up ↑
4886 4906          for (wid = codec->first_wid; wid <= codec->last_wid; wid++) {
4887 4907                  widget = codec->widget[wid];
4888 4908  
4889 4909                  /* check if it is an ADC widget */
4890 4910                  if (widget == NULL || widget->type != WTYPE_AUDIO_IN)
4891 4911                          continue;
4892 4912  
4893 4913                  if (path == NULL)
4894 4914                          path = kmem_zalloc(sizeof (audiohd_path_t), KM_SLEEP);
4895 4915                  else
4896      -                        bzero(path, sizeof (audiohd_port_t));
     4916 +                        bzero(path, sizeof (audiohd_path_t));
4897 4917                  path->adda_wid = wid;
4898 4918  
4899 4919                  for (i = 0; i < widget->nconns; i++) {
4900 4920                          retval = audiohd_find_output_pins(codec,
4901 4921                              widget->avail_conn[i], 0, path);
4902 4922                          if (retval == (DDI_SUCCESS)) {
4903 4923                                  path->codec = codec;
4904 4924                                  path->statep = statep;
4905 4925                                  path->path_type = LOOPBACK;
4906 4926                                  path->tag = ++rtag;
↓ open down ↓ 373 lines elided ↑ open up ↑
5280 5300                  if (codec == NULL)
5281 5301                          continue;
5282 5302                  pin = codec->first_pin;
5283 5303                  while (pin) {
5284 5304                          /* enable the unsolicited response of the pin */
5285 5305                          widget = codec->widget[pin->wid];
5286 5306                          if ((widget->widget_cap &
5287 5307                              (AUDIOHD_URCAP_MASK) &&
5288 5308                              (pin->cap & AUDIOHD_DTCCAP_MASK)) &&
5289 5309                              ((pin->device == DTYPE_LINEOUT) ||
     5310 +                            (pin->device == DTYPE_DIGIT_OUT) ||
5290 5311                              (pin->device == DTYPE_SPDIF_OUT) ||
5291 5312                              (pin->device == DTYPE_HP_OUT) ||
5292 5313                              (pin->device == DTYPE_MIC_IN))) {
5293 5314                                  urctrl = (uint8_t)(1 <<
5294 5315                                      (AUDIOHD_UR_ENABLE_OFF - 1));
5295 5316                                  urctrl |= (pin->wid & AUDIOHD_UR_TAG_MASK);
5296 5317                                  (void) audioha_codec_verb_get(statep,
5297 5318                                      codec->index,
5298 5319                                      pin->wid,
5299 5320                                      AUDIOHDC_VERB_SET_UNS_ENABLE, urctrl);
↓ open down ↓ 312 lines elided ↑ open up ↑
5612 5633                                      AUDIOHD_PIN_CONTP_MASK) ==
5613 5634                                      AUDIOHD_PIN_CON_FIXED)) {
5614 5635                                          statep->port[PORT_ADC]->index =
5615 5636                                              path->tag;
5616 5637                                          return;
5617 5638                                  }
5618 5639                          }
5619 5640                  }
5620 5641          }
5621 5642  }
     5643 +
5622 5644  /*
     5645 + * audiohd_setup_hdmi_dp()
     5646 + *
     5647 + * Description
     5648 + *
     5649 + *      Set up a basic channel mapping and a audio infoframe for a
     5650 + *      HDMI/DisplayPort pin widget. Due to lack of testing hardware
     5651 + *      this is limited to 2 channels for now.
     5652 + */
     5653 +static void
     5654 +audiohd_setup_hdmi_dp(audiohd_state_t *statep, uint8_t index, uint8_t id,
     5655 +    boolean_t hdmi)
     5656 +{
     5657 +        uint8_t chanmap[] = { 0, 1, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf };
     5658 +        uint8_t dp_infoframe[] = { 0x84, 0x1b, 0x44, 0x01, 0x00, 0x00, 0x02 };
     5659 +        uint8_t hdmi_infoframe[] = { 0x84, 0x01, 0x0a,
     5660 +            (-(0x84 + 0x01 + 0x0a + 0x01 + 0x02)) & 0xff,
     5661 +            0x01, 0x00, 0x00, 0x02 };
     5662 +        uint8_t *infoframe;
     5663 +        size_t infolen;
     5664 +        int i;
     5665 +
     5666 +        if (hdmi) {
     5667 +                infoframe = hdmi_infoframe;
     5668 +                infolen = sizeof (hdmi_infoframe);
     5669 +        } else {
     5670 +                infoframe = dp_infoframe;
     5671 +                infolen = sizeof (dp_infoframe);
     5672 +        }
     5673 +
     5674 +        /*
     5675 +         * Setup channel mapping. Only 2 channels supported for now.
     5676 +         */
     5677 +        for (i = 0; i != sizeof (chanmap); i++)
     5678 +                (void) audioha_codec_verb_get(statep, index, id,
     5679 +                    AUDIOHDC_VERB_SET_ASP_CHMAP, (chanmap[i] << 4) | i);
     5680 +
     5681 +        /*
     5682 +         * Send audio infoframe.
     5683 +         */
     5684 +        (void) audioha_codec_verb_get(statep, index, id,
     5685 +            AUDIOHDC_VERB_SET_DIP_INDEX, 0);
     5686 +        (void) audioha_codec_verb_get(statep, index, id,
     5687 +            AUDIOHDC_VERB_SET_DIP_XMIT, AUDIOHD_DIP_XMIT_STOP);
     5688 +
     5689 +        (void) audioha_codec_verb_get(statep, index, id,
     5690 +            AUDIOHDC_VERB_SET_DIP_INDEX, 0);
     5691 +        for (i = 0; i != AUDIOHD_DIP_DATA_LEN; i++)
     5692 +                (void) audioha_codec_verb_get(statep, index, id,
     5693 +                    AUDIOHDC_VERB_SET_DIP_DATA, 0);
     5694 +
     5695 +        (void) audioha_codec_verb_get(statep, index, id,
     5696 +            AUDIOHDC_VERB_SET_DIP_INDEX, 0);
     5697 +        for (i = 0; i != infolen; i++)
     5698 +                (void) audioha_codec_verb_get(statep, index, id,
     5699 +                    AUDIOHDC_VERB_SET_DIP_DATA, infoframe[i]);
     5700 +
     5701 +        (void) audioha_codec_verb_get(statep, index, id,
     5702 +            AUDIOHDC_VERB_SET_DIP_INDEX, 0);
     5703 +        (void) audioha_codec_verb_get(statep, index, id,
     5704 +            AUDIOHDC_VERB_SET_DIP_XMIT, AUDIOHD_DIP_XMIT_BEST_EFFORT);
     5705 +
     5706 +}
     5707 +
     5708 +/*
     5709 + * audiohd_get_eld()
     5710 + *
     5711 + * Description
     5712 + *
     5713 + *      Fetch the EDID-like data (ELD) from a pin that is a HDMI/DP
     5714 + *      display sink device. The data is coming tightly packed from
     5715 + *      hardware, unpack it into a audiohd_eld_t structure for easy
     5716 + *      access. We get the complete ELD, but we completely ignore the
     5717 + *      vendor specific part.
     5718 + */
     5719 +static audiohd_eld_t *
     5720 +audiohd_get_eld(audiohd_state_t *statep, uint8_t index, uint8_t id)
     5721 +{
     5722 +        uint8_t                 *buf;
     5723 +        audiohd_eld_t           *eld;
     5724 +        off_t                   sad_off;
     5725 +        uint32_t                rs;
     5726 +        size_t                  eldsz;
     5727 +        size_t                  i;
     5728 +
     5729 +        rs = audioha_codec_verb_get(statep, index, id,
     5730 +            AUDIOHDC_VERB_GET_DIP_SIZE, AUDIOHD_DIP_SIZE_ELD);
     5731 +
     5732 +        eldsz = (rs & AUDIOHD_DIP_SIZE_ELD_MASK) + 1;
     5733 +        if (eldsz < AUDIOHD_ELD_HDR_LEN)
     5734 +                return (NULL);
     5735 +
     5736 +        eldsz = MAX(eldsz, sizeof (audiohd_eld_t));
     5737 +
     5738 +        buf = kmem_zalloc(eldsz, KM_SLEEP);
     5739 +        eld = (audiohd_eld_t *)buf;
     5740 +
     5741 +        /*
     5742 +         * The device will return 0 for any offset that is beyond the length of
     5743 +         * ELD, so we don't have to check whether the size returned by DIP SIZE
     5744 +         * is less than sizeof (audiohd_eld_t).
     5745 +         */
     5746 +        for (i = 0; i != eldsz; i++)
     5747 +                buf[i] = audioha_codec_verb_get(statep, index, id,
     5748 +                    AUDIOHDC_VERB_GET_ELD, i);
     5749 +
     5750 +        if (eld->eld_ver != AUDIOHD_ELD_VER_2 &&
     5751 +            eld->eld_ver != AUDIOHD_ELD_VER_NODRV) {
     5752 +                kmem_free(buf, eldsz);
     5753 +                return (NULL);
     5754 +        }
     5755 +
     5756 +        eld->eld_size = eldsz;
     5757 +
     5758 +        /* move the CEA SADs to eld_cea_sad */
     5759 +        sad_off = offsetof(audiohd_eld_t, eld_monitor_name) + eld->eld_mnl;
     5760 +        bcopy(buf + sad_off, (void *)eld->eld_cea_sad,
     5761 +            sizeof (audiohd_sad_t) * eld->eld_sad_count);
     5762 +        bzero(buf + sad_off, offsetof(audiohd_eld_t, eld_cea_sad) - sad_off);
     5763 +
     5764 +        return (eld);
     5765 +}
     5766 +
     5767 +/*
5623 5768   * audiohd_pin_sense()
5624 5769   *
5625 5770   * Description
5626 5771   *
5627 5772   *      When the earphone is plugged into the jack associtated with the pin
5628 5773   *      complex, we disable the built in speaker. When the earphone is plugged
5629 5774   *      out of the jack, we enable the built in speaker.
     5775 + *
     5776 + *      When a digital pin complex reports valid EDID-like data (ELD), update
     5777 + *      it.
5630 5778   */
5631 5779  static void
5632 5780  audiohd_pin_sense(audiohd_state_t *statep, uint32_t resp, uint32_t respex)
5633 5781  {
     5782 +        audiohd_pin_t           *pin = NULL;
5634 5783          uint8_t                 index;
5635 5784          uint8_t                 id;
5636 5785          uint32_t                rs;
5637 5786          audiohd_widget_t        *widget;
5638      -        audiohd_pin_t           *pin;
5639 5787          hda_codec_t             *codec;
5640 5788  
5641 5789          index = respex & AUDIOHD_RIRB_CODEC_MASK;
5642 5790          id = resp >> (AUDIOHD_RIRB_WID_OFF - 1);
5643 5791  
5644 5792          codec = statep->codec[index];
5645 5793          if (codec == NULL)
5646 5794                  return;
5647 5795          widget = codec->widget[id];
5648 5796          if (widget == NULL)
5649 5797                  return;
5650 5798  
     5799 +        if (widget->type == WTYPE_PIN)
     5800 +                pin = (audiohd_pin_t *)widget->priv;
     5801 +
5651 5802          rs = audioha_codec_verb_get(statep, index, id,
5652 5803              AUDIOHDC_VERB_GET_PIN_SENSE, 0);
5653      -        if (rs & AUDIOHD_PIN_PRES_MASK) {
     5804 +
     5805 +        if ((widget->widget_cap & AUDIOHD_WIDCAP_DIGIT) != 0 &&
     5806 +            (rs & AUDIOHD_PIN_ELDV_MASK) != 0) {
     5807 +                /* updated EDID-like data */
     5808 +                if (pin != NULL) {
     5809 +                        if (pin->eld != NULL)
     5810 +                                kmem_free(pin->eld, pin->eld->eld_size);
     5811 +                        pin->eld = audiohd_get_eld(statep, index, id);
     5812 +                }
     5813 +        } else if (rs & AUDIOHD_PIN_PRES_MASK) {
5654 5814                  /* A MIC is plugged in, we select the MIC as input */
5655      -                if ((widget->type == WTYPE_PIN) &&
5656      -                    (pin = (audiohd_pin_t *)widget->priv) &&
5657      -                    (pin->device == DTYPE_MIC_IN)) {
     5815 +                if (pin != NULL && pin->device == DTYPE_MIC_IN) {
5658 5816                          audiohd_select_mic(statep, index, id, 1);
5659 5817                          return;
5660 5818                  }
5661 5819                  /* output pin is plugged */
5662 5820                  audiohd_change_speaker_state(statep, AUDIOHD_SP_OFF);
5663 5821          } else {
5664 5822                  /*
5665 5823                   * A MIC is unplugged, we select the built in MIC
5666 5824                   * as input.
5667 5825                   */
↓ open down ↓ 241 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX