The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/pci/hda/hdaa_patches.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
    5  * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
    6  * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 /*
   32  * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
   33  */
   34 
   35 #ifdef HAVE_KERNEL_OPTION_HEADERS
   36 #include "opt_snd.h"
   37 #endif
   38 
   39 #include <dev/sound/pcm/sound.h>
   40 
   41 #include <sys/ctype.h>
   42 
   43 #include <dev/sound/pci/hda/hdac.h>
   44 #include <dev/sound/pci/hda/hdaa.h>
   45 #include <dev/sound/pci/hda/hda_reg.h>
   46 
   47 #include "pin_patch.h"
   48 #include "pin_patch_realtek.h"
   49 
   50 SND_DECLARE_FILE("$FreeBSD$");
   51 
   52 static const struct {
   53         uint32_t model;
   54         uint32_t id;
   55         uint32_t subsystemid;
   56         uint32_t set, unset;
   57         uint32_t gpio;
   58 } hdac_quirks[] = {
   59         /*
   60          * XXX Force stereo quirk. Monoural recording / playback
   61          *     on few codecs (especially ALC880) seems broken or
   62          *     perhaps unsupported.
   63          */
   64         { HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL,
   65             HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
   66             0 },
   67         { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL,
   68             0, 0,
   69             HDAA_GPIO_SET(0) },
   70         { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL,
   71             0, 0,
   72             HDAA_GPIO_SET(0) },
   73         { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
   74             0, 0,
   75             HDAA_GPIO_SET(0) },
   76         { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
   77             0, 0,
   78             HDAA_GPIO_SET(0) },
   79         { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
   80             0, 0,
   81             HDAA_GPIO_SET(0) },
   82         { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
   83             0, 0,
   84             HDAA_GPIO_SET(0) },
   85         { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
   86             HDAA_QUIRK_EAPDINV, 0,
   87             0 },
   88         { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
   89             HDAA_QUIRK_EAPDINV, 0,
   90             0 },
   91         { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
   92             HDAA_QUIRK_OVREF, 0,
   93             0 },
   94         { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
   95             HDAA_QUIRK_OVREF, 0,
   96             0 },
   97         /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL,
   98             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
   99             0 },*/
  100         { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
  101             0, 0,
  102             HDAA_GPIO_SET(1) },
  103         { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
  104             HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
  105             0 },
  106         { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
  107             HDAA_QUIRK_EAPDINV, 0,
  108             0 },
  109         { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL,
  110             HDAA_QUIRK_OVREF50, 0,
  111             HDAA_GPIO_SET(0) },
  112         { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL,
  113             0, 0,
  114             HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
  115         { APPLE_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL,
  116             0, 0,
  117             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
  118         { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
  119             0, 0,
  120             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
  121         { APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
  122             0, 0,
  123             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
  124         { HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
  125             0, 0,
  126             HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
  127         { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
  128             0, 0,
  129             HDAA_GPIO_SET(0) },
  130         { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
  131             0, 0,
  132             HDAA_GPIO_SET(2) },
  133         { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
  134             0, 0,
  135             HDAA_GPIO_SET(0) },
  136         { HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
  137             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
  138             0 },
  139         { HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
  140             HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
  141             0 },
  142         { HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
  143             0, HDAA_QUIRK_FORCESTEREO,
  144             0 },
  145         /* Mac Pro 1,1 requires ovref for proper volume level. */
  146         { 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
  147             0, HDAA_QUIRK_OVREF,
  148             0 }
  149 };
  150 
  151 static struct pin_patch_t *
  152 match_pin_patches(int vendor_id, int vendor_subid)
  153 {
  154         for (int ci = 0; ci < nitems(realtek_model_pin_patches); ci++) {
  155                 struct hdaa_model_pin_patch_t *p = &realtek_model_pin_patches[ci];
  156                 if (vendor_id != p->id)
  157                         continue;
  158                 for (struct model_pin_patch_t *pp =  p->patches; pp->models; pp++) {
  159                         for (struct pin_machine_model_t *model = pp->models; model->id != 0; model++) {
  160                                 if (HDA_DEV_MATCH(model->id, vendor_subid))
  161                                         return (pp->pin_patches);
  162                         }
  163                 }
  164         }
  165 
  166         return (0);
  167 }
  168 
  169 static void
  170 hdac_pin_patch(struct hdaa_widget *w)
  171 {
  172         const char *patch_str = NULL;
  173         uint32_t config, orig, id, subid;
  174         nid_t nid = w->nid;
  175 
  176         config = orig = w->wclass.pin.config;
  177         id = hdaa_codec_id(w->devinfo);
  178         subid = hdaa_card_id(w->devinfo);
  179 
  180         if (id == HDA_CODEC_ALC883 && HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid)) {
  181                 switch (nid) {
  182                 case 25:
  183                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
  184                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
  185                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
  186                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
  187                         break;
  188                 case 28:
  189                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
  190                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
  191                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
  192                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
  193                         break;
  194                 }
  195         } else if (id == HDA_CODEC_CX20549 && subid ==
  196             HP_V3000_SUBVENDOR) {
  197                 switch (nid) {
  198                 case 18:
  199                         config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
  200                         config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
  201                         break;
  202                 case 20:
  203                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
  204                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
  205                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
  206                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
  207                         break;
  208                 case 21:
  209                         config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
  210                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
  211                         config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
  212                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
  213                         break;
  214                 }
  215         } else if (id == HDA_CODEC_CX20551 && subid ==
  216             HP_DV5000_SUBVENDOR) {
  217                 switch (nid) {
  218                 case 20:
  219                 case 21:
  220                         config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
  221                         config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
  222                         break;
  223                 }
  224         }
  225 
  226         /* New patches */
  227         if (id == HDA_CODEC_AD1984A &&
  228             subid == LENOVO_X300_SUBVENDOR) {
  229                 switch (nid) {
  230                 case 17: /* Headphones with redirection */
  231                         patch_str = "as=1 seq=15";
  232                         break;
  233                 case 20: /* Two mics together */
  234                         patch_str = "as=2 seq=15";
  235                         break;
  236                 }
  237         } else if (id == HDA_CODEC_AD1986A &&
  238             (subid == ASUS_M2NPVMX_SUBVENDOR ||
  239             subid == ASUS_A8NVMCSM_SUBVENDOR ||
  240             subid == ASUS_P5PL2_SUBVENDOR)) {
  241                 switch (nid) {
  242                 case 26: /* Headphones with redirection */
  243                         patch_str = "as=1 seq=15";
  244                         break;
  245                 case 28: /* 5.1 out => 2.0 out + 1 input */
  246                         patch_str = "device=Line-in as=8 seq=1";
  247                         break;
  248                 case 29: /* Can't use this as input, as the only available mic
  249                           * preamplifier is busy by front panel mic (nid 31).
  250                           * If you want to use this rear connector as mic input,
  251                           * you have to disable the front panel one. */
  252                         patch_str = "as=0";
  253                         break;
  254                 case 31: /* Lot of inputs configured with as=15 and unusable */
  255                         patch_str = "as=8 seq=3";
  256                         break;
  257                 case 32:
  258                         patch_str = "as=8 seq=4";
  259                         break;
  260                 case 34:
  261                         patch_str = "as=8 seq=5";
  262                         break;
  263                 case 36:
  264                         patch_str = "as=8 seq=6";
  265                         break;
  266                 }
  267         } else if (id == HDA_CODEC_CX20561 &&
  268             subid == LENOVO_B450_SUBVENDOR) {
  269                 switch (nid) {
  270                 case 22:
  271                         patch_str = "as=1 seq=15";
  272                         break;
  273                 }
  274         } else if (id == HDA_CODEC_CX20561 &&
  275             subid == LENOVO_T400_SUBVENDOR) {
  276                 switch (nid) {
  277                 case 22:
  278                         patch_str = "as=1 seq=15";
  279                         break;
  280                 case 26:
  281                         patch_str = "as=1 seq=0";
  282                         break;
  283                 }
  284         } else if (id == HDA_CODEC_CX20590 &&
  285             (subid == LENOVO_X1_SUBVENDOR ||
  286             subid == LENOVO_X220_SUBVENDOR ||
  287             subid == LENOVO_T420_SUBVENDOR ||
  288             subid == LENOVO_T520_SUBVENDOR ||
  289             subid == LENOVO_G580_SUBVENDOR)) {
  290                 switch (nid) {
  291                 case 25:
  292                         patch_str = "as=1 seq=15";
  293                         break;
  294                 /*
  295                  * Group onboard mic and headphone mic
  296                  * together.  Fixes onboard mic.
  297                  */
  298                 case 27:
  299                         patch_str = "as=2 seq=15";
  300                         break;
  301                 case 35:
  302                         patch_str = "as=2";
  303                         break;
  304                 }
  305         } else if (id == HDA_CODEC_ALC235 && subid == ASUS_GL553VE_SUBVENDOR) {
  306                 switch (nid) {
  307                 case 33:
  308                         patch_str = "as=1 seq=15";
  309                         break;
  310                 }
  311         } else if (id == HDA_CODEC_ALC256 && (subid == DELL_I7577_SUBVENDOR ||
  312             subid == DELL_L7480_SUBVENDOR)) {
  313                 switch (nid) {
  314                 case 20:
  315                         patch_str = "as=1 seq=0";
  316                         break;
  317                 case 33:
  318                         patch_str = "as=1 seq=15";
  319                         break;
  320                 }
  321         } else if (id == HDA_CODEC_ALC257 &&
  322             (subid == LENOVO_L5AMD_SUBVENDOR ||
  323             subid == LENOVO_L5INTEL_SUBVENDOR)) {
  324                 switch (nid) {
  325                 case 20:
  326                         patch_str = "as=1 seq=0";
  327                         break;
  328                 case 33:
  329                         patch_str = "as=1 seq=15";
  330                         break;
  331                 }
  332         } else if (id == HDA_CODEC_IDT92HD95B &&
  333             (subid == FRAMEWORK_LAPTOP_0001_SUBVENDOR ||
  334             subid == FRAMEWORK_LAPTOP_0002_SUBVENDOR)) {
  335                 switch (nid) {
  336                 case 10:
  337                         patch_str = "as=1 seq=15 color=Black loc=Left";
  338                         break;
  339                 case 11:
  340                         patch_str = "as=3 seq=15 color=Black loc=Left";
  341                         break;
  342                 }
  343         } else {
  344                 /*
  345                  * loop over hdaa_model_pin_patch
  346                  */
  347                 struct pin_patch_t *pin_patches = NULL;
  348 
  349                 pin_patches = match_pin_patches(id, subid);
  350 
  351                 if (pin_patches != NULL) {
  352                         for (struct pin_patch_t *patch = pin_patches; patch->type; patch++) {
  353                                 if (nid == patch->nid) {
  354                                         switch (patch->type) {
  355                                         case PIN_PATCH_TYPE_STRING:
  356                                                 patch_str = patch->patch.string;
  357                                                 break;
  358                                         case PIN_PATCH_TYPE_MASK:
  359                                                 config &= ~patch->patch.mask[0];
  360                                                 config |= patch->patch.mask[1];
  361                                                 break;
  362                                         case PIN_PATCH_TYPE_OVERRIDE:
  363                                                 config = patch->patch.override;
  364                                                 break;
  365                                         default:
  366                                                 /* should panic hard */
  367                                                 break;
  368                                         }
  369                                         break;
  370                                 }
  371                         }
  372                 }
  373         }
  374 
  375         if (patch_str != NULL)
  376                 config = hdaa_widget_pin_patch(config, patch_str);
  377         HDA_BOOTVERBOSE(
  378                 if (config != orig)
  379                         device_printf(w->devinfo->dev,
  380                             "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
  381                             nid, orig, config);
  382         );
  383         w->wclass.pin.config = config;
  384 }
  385 
  386 static void
  387 hdaa_widget_patch(struct hdaa_widget *w)
  388 {
  389         struct hdaa_devinfo *devinfo = w->devinfo;
  390         uint32_t orig;
  391         nid_t beeper = -1;
  392 
  393         orig = w->param.widget_cap;
  394         /* On some codecs beeper is an input pin, but it is not recordable
  395            alone. Also most of BIOSes does not declare beeper pin.
  396            Change beeper pin node type to beeper to help parser. */
  397         switch (hdaa_codec_id(devinfo)) {
  398         case HDA_CODEC_AD1882:
  399         case HDA_CODEC_AD1883:
  400         case HDA_CODEC_AD1984:
  401         case HDA_CODEC_AD1984A:
  402         case HDA_CODEC_AD1984B:
  403         case HDA_CODEC_AD1987:
  404         case HDA_CODEC_AD1988:
  405         case HDA_CODEC_AD1988B:
  406         case HDA_CODEC_AD1989B:
  407                 beeper = 26;
  408                 break;
  409         case HDA_CODEC_ALC260:
  410                 beeper = 23;
  411                 break;
  412         }
  413         if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
  414             hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
  415                 beeper = 29;
  416         if (w->nid == beeper) {
  417                 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
  418                 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
  419                     HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
  420                 w->waspin = 1;
  421         }
  422         /*
  423          * Clear "digital" flag from digital mic input, as its signal then goes
  424          * to "analog" mixer and this separation just limits functionaity.
  425          */
  426         if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
  427             w->nid == 23)
  428                 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
  429         HDA_BOOTVERBOSE(
  430                 if (w->param.widget_cap != orig) {
  431                         device_printf(w->devinfo->dev,
  432                             "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
  433                             w->nid, orig, w->param.widget_cap);
  434                 }
  435         );
  436 
  437         if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
  438                 hdac_pin_patch(w);
  439 }
  440 
  441 void
  442 hdaa_patch(struct hdaa_devinfo *devinfo)
  443 {
  444         struct hdaa_widget *w;
  445         uint32_t id, subid, subsystemid;
  446         int i;
  447 
  448         id = hdaa_codec_id(devinfo);
  449         subid = hdaa_card_id(devinfo);
  450         subsystemid = hda_get_subsystem_id(devinfo->dev);
  451 
  452         /*
  453          * Quirks
  454          */
  455         for (i = 0; i < nitems(hdac_quirks); i++) {
  456                 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
  457                     HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
  458                     HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
  459                         continue;
  460                 devinfo->quirks |= hdac_quirks[i].set;
  461                 devinfo->quirks &= ~(hdac_quirks[i].unset);
  462                 devinfo->gpio = hdac_quirks[i].gpio;
  463         }
  464 
  465         /* Apply per-widget patch. */
  466         for (i = devinfo->startnode; i < devinfo->endnode; i++) {
  467                 w = hdaa_widget_get(devinfo, i);
  468                 if (w == NULL)
  469                         continue;
  470                 hdaa_widget_patch(w);
  471         }
  472 
  473         switch (id) {
  474         case HDA_CODEC_AD1983:
  475                 /*
  476                  * This CODEC has several possible usages, but none
  477                  * fit the parser best. Help parser to choose better.
  478                  */
  479                 /* Disable direct unmixed playback to get pcm volume. */
  480                 w = hdaa_widget_get(devinfo, 5);
  481                 if (w != NULL)
  482                         w->connsenable[0] = 0;
  483                 w = hdaa_widget_get(devinfo, 6);
  484                 if (w != NULL)
  485                         w->connsenable[0] = 0;
  486                 w = hdaa_widget_get(devinfo, 11);
  487                 if (w != NULL)
  488                         w->connsenable[0] = 0;
  489                 /* Disable mic and line selectors. */
  490                 w = hdaa_widget_get(devinfo, 12);
  491                 if (w != NULL)
  492                         w->connsenable[1] = 0;
  493                 w = hdaa_widget_get(devinfo, 13);
  494                 if (w != NULL)
  495                         w->connsenable[1] = 0;
  496                 /* Disable recording from mono playback mix. */
  497                 w = hdaa_widget_get(devinfo, 20);
  498                 if (w != NULL)
  499                         w->connsenable[3] = 0;
  500                 break;
  501         case HDA_CODEC_AD1986A:
  502                 /*
  503                  * This CODEC has overcomplicated input mixing.
  504                  * Make some cleaning there.
  505                  */
  506                 /* Disable input mono mixer. Not needed and not supported. */
  507                 w = hdaa_widget_get(devinfo, 43);
  508                 if (w != NULL)
  509                         w->enable = 0;
  510                 /* Disable any with any input mixing mesh. Use separately. */
  511                 w = hdaa_widget_get(devinfo, 39);
  512                 if (w != NULL)
  513                         w->enable = 0;
  514                 w = hdaa_widget_get(devinfo, 40);
  515                 if (w != NULL)
  516                         w->enable = 0;
  517                 w = hdaa_widget_get(devinfo, 41);
  518                 if (w != NULL)
  519                         w->enable = 0;
  520                 w = hdaa_widget_get(devinfo, 42);
  521                 if (w != NULL)
  522                         w->enable = 0;
  523                 /* Disable duplicate mixer node connector. */
  524                 w = hdaa_widget_get(devinfo, 15);
  525                 if (w != NULL)
  526                         w->connsenable[3] = 0;
  527                 /* There is only one mic preamplifier, use it effectively. */
  528                 w = hdaa_widget_get(devinfo, 31);
  529                 if (w != NULL) {
  530                         if ((w->wclass.pin.config &
  531                             HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
  532                             HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
  533                                 w = hdaa_widget_get(devinfo, 16);
  534                                 if (w != NULL)
  535                                     w->connsenable[2] = 0;
  536                         } else {
  537                                 w = hdaa_widget_get(devinfo, 15);
  538                                 if (w != NULL)
  539                                     w->connsenable[0] = 0;
  540                         }
  541                 }
  542                 w = hdaa_widget_get(devinfo, 32);
  543                 if (w != NULL) {
  544                         if ((w->wclass.pin.config &
  545                             HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
  546                             HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
  547                                 w = hdaa_widget_get(devinfo, 16);
  548                                 if (w != NULL)
  549                                     w->connsenable[0] = 0;
  550                         } else {
  551                                 w = hdaa_widget_get(devinfo, 15);
  552                                 if (w != NULL)
  553                                     w->connsenable[1] = 0;
  554                         }
  555                 }
  556 
  557                 if (subid == ASUS_A8X_SUBVENDOR) {
  558                         /*
  559                          * This is just plain ridiculous.. There
  560                          * are several A8 series that share the same
  561                          * pci id but works differently (EAPD).
  562                          */
  563                         w = hdaa_widget_get(devinfo, 26);
  564                         if (w != NULL && w->type ==
  565                             HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
  566                             (w->wclass.pin.config &
  567                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
  568                             HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
  569                                 devinfo->quirks &=
  570                                     ~HDAA_QUIRK_EAPDINV;
  571                 }
  572                 break;
  573         case HDA_CODEC_AD1981HD:
  574                 /*
  575                  * This CODEC has very unusual design with several
  576                  * points inappropriate for the present parser.
  577                  */
  578                 /* Disable recording from mono playback mix. */
  579                 w = hdaa_widget_get(devinfo, 21);
  580                 if (w != NULL)
  581                         w->connsenable[3] = 0;
  582                 /* Disable rear to front mic mixer, use separately. */
  583                 w = hdaa_widget_get(devinfo, 31);
  584                 if (w != NULL)
  585                         w->enable = 0;
  586                 /* Disable direct playback, use mixer. */
  587                 w = hdaa_widget_get(devinfo, 5);
  588                 if (w != NULL)
  589                         w->connsenable[0] = 0;
  590                 w = hdaa_widget_get(devinfo, 6);
  591                 if (w != NULL)
  592                         w->connsenable[0] = 0;
  593                 w = hdaa_widget_get(devinfo, 9);
  594                 if (w != NULL)
  595                         w->connsenable[0] = 0;
  596                 w = hdaa_widget_get(devinfo, 24);
  597                 if (w != NULL)
  598                         w->connsenable[0] = 0;
  599                 break;
  600         case HDA_CODEC_ALC269:
  601                 /*
  602                  * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
  603                  * that mutes speaker if unused mixer at NID 15 is muted.
  604                  * Probably CODEC incorrectly reports internal connections.
  605                  * Hide that muter from the driver.  There are several CODECs
  606                  * sharing this ID and I have not enough information about
  607                  * them to implement more universal solution.
  608                  */
  609                 if (subid == 0x84371043) {
  610                         w = hdaa_widget_get(devinfo, 15);
  611                         if (w != NULL)
  612                                 w->param.inamp_cap = 0;
  613                 }
  614                 break;
  615         case HDA_CODEC_CX20582:
  616         case HDA_CODEC_CX20583:
  617         case HDA_CODEC_CX20584:
  618         case HDA_CODEC_CX20585:
  619         case HDA_CODEC_CX20590:
  620                 /*
  621                  * These codecs have extra connectivity on record side
  622                  * too reach for the present parser.
  623                  */
  624                 w = hdaa_widget_get(devinfo, 20);
  625                 if (w != NULL)
  626                         w->connsenable[1] = 0;
  627                 w = hdaa_widget_get(devinfo, 21);
  628                 if (w != NULL)
  629                         w->connsenable[1] = 0;
  630                 w = hdaa_widget_get(devinfo, 22);
  631                 if (w != NULL)
  632                         w->connsenable[0] = 0;
  633                 break;
  634         case HDA_CODEC_VT1708S_0:
  635         case HDA_CODEC_VT1708S_1:
  636         case HDA_CODEC_VT1708S_2:
  637         case HDA_CODEC_VT1708S_3:
  638         case HDA_CODEC_VT1708S_4:
  639         case HDA_CODEC_VT1708S_5:
  640         case HDA_CODEC_VT1708S_6:
  641         case HDA_CODEC_VT1708S_7:
  642                 /*
  643                  * These codecs have hidden mic boost controls.
  644                  */
  645                 w = hdaa_widget_get(devinfo, 26);
  646                 if (w != NULL)
  647                         w->param.inamp_cap =
  648                             (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
  649                             (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
  650                             (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
  651                 w = hdaa_widget_get(devinfo, 30);
  652                 if (w != NULL)
  653                         w->param.inamp_cap =
  654                             (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
  655                             (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
  656                             (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
  657                 break;
  658         }
  659 }
  660 
  661 static uint32_t
  662 hdaa_read_coef(device_t dev, nid_t nid, uint16_t idx)
  663 {
  664 
  665         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
  666         return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid)));
  667 }
  668 
  669 static uint32_t
  670 hdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val)
  671 {
  672 
  673         hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
  674         return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val)));
  675 }
  676 
  677 void
  678 hdaa_patch_direct(struct hdaa_devinfo *devinfo)
  679 {
  680         device_t dev = devinfo->dev;
  681         uint32_t id, subid, val;
  682 
  683         id = hdaa_codec_id(devinfo);
  684         subid = hdaa_card_id(devinfo);
  685 
  686         switch (id) {
  687         case HDA_CODEC_VT1708S_0:
  688         case HDA_CODEC_VT1708S_1:
  689         case HDA_CODEC_VT1708S_2:
  690         case HDA_CODEC_VT1708S_3:
  691         case HDA_CODEC_VT1708S_4:
  692         case HDA_CODEC_VT1708S_5:
  693         case HDA_CODEC_VT1708S_6:
  694         case HDA_CODEC_VT1708S_7:
  695                 /* Enable Mic Boost Volume controls. */
  696                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
  697                     0xf98, 0x01));
  698                 /* Fall though */
  699         case HDA_CODEC_VT1818S:
  700                 /* Don't bypass mixer. */
  701                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
  702                     0xf88, 0xc0));
  703                 break;
  704         case HDA_CODEC_ALC1150:
  705                 if (subid == 0xd9781462) {
  706                         /* Too low volume on MSI H170 GAMING M3. */
  707                         hdaa_write_coef(dev, 0x20, 0x07, 0x7cb);
  708                 }
  709                 break;
  710         }
  711         if (id == HDA_CODEC_ALC255 || id == HDA_CODEC_ALC256) {
  712                 val = hdaa_read_coef(dev, 0x20, 0x46);
  713                 hdaa_write_coef(dev, 0x20, 0x46, val|0x3000);
  714         }
  715         if (subid == APPLE_INTEL_MAC)
  716                 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
  717                     0x7e7, 0));
  718         if (id == HDA_CODEC_ALC269) {
  719                 if (subid == 0x16e31043 || subid == 0x831a1043 ||
  720                     subid == 0x834a1043 || subid == 0x83981043 ||
  721                     subid == 0x83ce1043) {
  722                         /*
  723                          * The digital mics on some Asus laptops produce
  724                          * differential signals instead of expected stereo.
  725                          * That results in silence if downmixing to mono.
  726                          * To workaround, make codec handle the signal as mono.
  727                          */
  728                         val = hdaa_read_coef(dev, 0x20, 0x07);
  729                         hdaa_write_coef(dev, 0x20, 0x07, val|0x80);
  730                 }
  731                 if (subid == 0x15171043) {
  732                         /* Increase output amp on ASUS UX31A by +5dB. */
  733                         hdaa_write_coef(dev, 0x20, 0x12, 0x2800);
  734                 }
  735         }
  736 }

Cache object: 1e3e9457ff60280df2e556e570576249


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.