LCOV - code coverage report
Current view: top level - sound/pci/ac97 - ac97_patch.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1183 0.0 %
Date: 2014-04-07 Functions: 0 169 0.0 %
Branches: 0 567 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
       3                 :            :  *  Universal interface for Audio Codec '97
       4                 :            :  *
       5                 :            :  *  For more details look to AC '97 component specification revision 2.2
       6                 :            :  *  by Intel Corporation (http://developer.intel.com) and to datasheets
       7                 :            :  *  for specific codecs.
       8                 :            :  *
       9                 :            :  *
      10                 :            :  *   This program is free software; you can redistribute it and/or modify
      11                 :            :  *   it under the terms of the GNU General Public License as published by
      12                 :            :  *   the Free Software Foundation; either version 2 of the License, or
      13                 :            :  *   (at your option) any later version.
      14                 :            :  *
      15                 :            :  *   This program is distributed in the hope that it will be useful,
      16                 :            :  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
      17                 :            :  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18                 :            :  *   GNU General Public License for more details.
      19                 :            :  *
      20                 :            :  *   You should have received a copy of the GNU General Public License
      21                 :            :  *   along with this program; if not, write to the Free Software
      22                 :            :  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
      23                 :            :  *
      24                 :            :  */
      25                 :            : 
      26                 :            : #include "ac97_local.h"
      27                 :            : #include "ac97_patch.h"
      28                 :            : 
      29                 :            : /*
      30                 :            :  *  Forward declarations
      31                 :            :  */
      32                 :            : 
      33                 :            : static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
      34                 :            :                                                     const char *name);
      35                 :            : static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
      36                 :            :                                 const unsigned int *tlv, const char **slaves);
      37                 :            : 
      38                 :            : /*
      39                 :            :  *  Chip specific initialization
      40                 :            :  */
      41                 :            : 
      42                 :          0 : static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontrol_new *controls, int count)
      43                 :            : {
      44                 :            :         int idx, err;
      45                 :            : 
      46         [ #  # ]:          0 :         for (idx = 0; idx < count; idx++)
      47         [ #  # ]:          0 :                 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&controls[idx], ac97))) < 0)
      48                 :            :                         return err;
      49                 :            :         return 0;
      50                 :            : }
      51                 :            : 
      52                 :            : /* replace with a new TLV */
      53                 :          0 : static void reset_tlv(struct snd_ac97 *ac97, const char *name,
      54                 :            :                       const unsigned int *tlv)
      55                 :            : {
      56                 :            :         struct snd_ctl_elem_id sid;
      57                 :            :         struct snd_kcontrol *kctl;
      58                 :          0 :         memset(&sid, 0, sizeof(sid));
      59                 :          0 :         strcpy(sid.name, name);
      60                 :          0 :         sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
      61                 :          0 :         kctl = snd_ctl_find_id(ac97->bus->card, &sid);
      62 [ #  # ][ #  # ]:          0 :         if (kctl && kctl->tlv.p)
      63                 :          0 :                 kctl->tlv.p = tlv;
      64                 :          0 : }
      65                 :            : 
      66                 :            : /* set to the page, update bits and restore the page */
      67                 :          0 : static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
      68                 :            : {
      69                 :            :         unsigned short page_save;
      70                 :            :         int ret;
      71                 :            : 
      72                 :          0 :         mutex_lock(&ac97->page_mutex);
      73                 :          0 :         page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
      74                 :          0 :         snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
      75                 :          0 :         ret = snd_ac97_update_bits(ac97, reg, mask, value);
      76                 :          0 :         snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
      77                 :          0 :         mutex_unlock(&ac97->page_mutex); /* unlock paging */
      78                 :          0 :         return ret;
      79                 :            : }
      80                 :            : 
      81                 :            : /*
      82                 :            :  * shared line-in/mic controls
      83                 :            :  */
      84                 :          0 : static int ac97_enum_text_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo,
      85                 :            :                                const char **texts, unsigned int nums)
      86                 :            : {
      87                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
      88                 :          0 :         uinfo->count = 1;
      89                 :          0 :         uinfo->value.enumerated.items = nums;
      90         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > nums - 1)
      91                 :          0 :                 uinfo->value.enumerated.item = nums - 1;
      92                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
      93                 :          0 :         return 0;
      94                 :            : }
      95                 :            : 
      96                 :          0 : static int ac97_surround_jack_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
      97                 :            : {
      98                 :            :         static const char *texts[] = { "Shared", "Independent" };
      99                 :          0 :         return ac97_enum_text_info(kcontrol, uinfo, texts, 2);
     100                 :            : }
     101                 :            : 
     102                 :          0 : static int ac97_surround_jack_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     103                 :            : {
     104                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     105                 :            : 
     106                 :          0 :         ucontrol->value.enumerated.item[0] = ac97->indep_surround;
     107                 :          0 :         return 0;
     108                 :            : }
     109                 :            : 
     110                 :          0 : static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     111                 :            : {
     112                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     113                 :          0 :         unsigned char indep = !!ucontrol->value.enumerated.item[0];
     114                 :            : 
     115         [ #  # ]:          0 :         if (indep != ac97->indep_surround) {
     116                 :          0 :                 ac97->indep_surround = indep;
     117         [ #  # ]:          0 :                 if (ac97->build_ops->update_jacks)
     118                 :          0 :                         ac97->build_ops->update_jacks(ac97);
     119                 :            :                 return 1;
     120                 :            :         }
     121                 :            :         return 0;
     122                 :            : }
     123                 :            : 
     124                 :          0 : static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
     125                 :            : {
     126                 :            :         static const char *texts[] = { "2ch", "4ch", "6ch", "8ch" };
     127                 :          0 :         return ac97_enum_text_info(kcontrol, uinfo, texts,
     128                 :          0 :                 kcontrol->private_value);
     129                 :            : }
     130                 :            : 
     131                 :          0 : static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     132                 :            : {
     133                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     134                 :            : 
     135                 :          0 :         ucontrol->value.enumerated.item[0] = ac97->channel_mode;
     136                 :          0 :         return 0;
     137                 :            : }
     138                 :            : 
     139                 :          0 : static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     140                 :            : {
     141                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     142                 :          0 :         unsigned char mode = ucontrol->value.enumerated.item[0];
     143                 :            : 
     144         [ #  # ]:          0 :         if (mode >= kcontrol->private_value)
     145                 :            :                 return -EINVAL;
     146                 :            : 
     147         [ #  # ]:          0 :         if (mode != ac97->channel_mode) {
     148                 :          0 :                 ac97->channel_mode = mode;
     149         [ #  # ]:          0 :                 if (ac97->build_ops->update_jacks)
     150                 :          0 :                         ac97->build_ops->update_jacks(ac97);
     151                 :            :                 return 1;
     152                 :            :         }
     153                 :            :         return 0;
     154                 :            : }
     155                 :            : 
     156                 :            : #define AC97_SURROUND_JACK_MODE_CTL \
     157                 :            :         { \
     158                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
     159                 :            :                 .name   = "Surround Jack Mode", \
     160                 :            :                 .info = ac97_surround_jack_mode_info, \
     161                 :            :                 .get = ac97_surround_jack_mode_get, \
     162                 :            :                 .put = ac97_surround_jack_mode_put, \
     163                 :            :         }
     164                 :            : /* 6ch */
     165                 :            : #define AC97_CHANNEL_MODE_CTL \
     166                 :            :         { \
     167                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
     168                 :            :                 .name   = "Channel Mode", \
     169                 :            :                 .info = ac97_channel_mode_info, \
     170                 :            :                 .get = ac97_channel_mode_get, \
     171                 :            :                 .put = ac97_channel_mode_put, \
     172                 :            :                 .private_value = 3, \
     173                 :            :         }
     174                 :            : /* 4ch */
     175                 :            : #define AC97_CHANNEL_MODE_4CH_CTL \
     176                 :            :         { \
     177                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
     178                 :            :                 .name   = "Channel Mode", \
     179                 :            :                 .info = ac97_channel_mode_info, \
     180                 :            :                 .get = ac97_channel_mode_get, \
     181                 :            :                 .put = ac97_channel_mode_put, \
     182                 :            :                 .private_value = 2, \
     183                 :            :         }
     184                 :            : /* 8ch */
     185                 :            : #define AC97_CHANNEL_MODE_8CH_CTL \
     186                 :            :         { \
     187                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, \
     188                 :            :                 .name   = "Channel Mode", \
     189                 :            :                 .info = ac97_channel_mode_info, \
     190                 :            :                 .get = ac97_channel_mode_get, \
     191                 :            :                 .put = ac97_channel_mode_put, \
     192                 :            :                 .private_value = 4, \
     193                 :            :         }
     194                 :            : 
     195                 :            : static inline int is_surround_on(struct snd_ac97 *ac97)
     196                 :            : {
     197                 :          0 :         return ac97->channel_mode >= 1;
     198                 :            : }
     199                 :            : 
     200                 :            : static inline int is_clfe_on(struct snd_ac97 *ac97)
     201                 :            : {
     202                 :          0 :         return ac97->channel_mode >= 2;
     203                 :            : }
     204                 :            : 
     205                 :            : /* system has shared jacks with surround out enabled */
     206                 :          0 : static inline int is_shared_surrout(struct snd_ac97 *ac97)
     207                 :            : {
     208 [ #  # ][ #  # ]:          0 :         return !ac97->indep_surround && is_surround_on(ac97);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     209                 :            : }
     210                 :            : 
     211                 :            : /* system has shared jacks with center/lfe out enabled */
     212                 :          0 : static inline int is_shared_clfeout(struct snd_ac97 *ac97)
     213                 :            : {
     214 [ #  # ][ #  # ]:          0 :         return !ac97->indep_surround && is_clfe_on(ac97);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     215                 :            : }
     216                 :            : 
     217                 :            : /* system has shared jacks with line in enabled */
     218                 :          0 : static inline int is_shared_linein(struct snd_ac97 *ac97)
     219                 :            : {
     220 [ #  # ][ #  # ]:          0 :         return !ac97->indep_surround && !is_surround_on(ac97);
         [ #  # ][ #  # ]
     221                 :            : }
     222                 :            : 
     223                 :            : /* system has shared jacks with mic in enabled */
     224                 :          0 : static inline int is_shared_micin(struct snd_ac97 *ac97)
     225                 :            : {
     226 [ #  # ][ #  # ]:          0 :         return !ac97->indep_surround && !is_clfe_on(ac97);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     227                 :            : }
     228                 :            : 
     229                 :          0 : static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97)
     230                 :            : {
     231                 :            :         return is_surround_on(ac97);
     232                 :            : }
     233                 :            : 
     234                 :            : /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
     235                 :            : /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */
     236                 :            : 
     237                 :            : /* It is possible to indicate to the Yamaha YMF7x3 the type of
     238                 :            :    speakers being used. */
     239                 :            : 
     240                 :          0 : static int snd_ac97_ymf7x3_info_speaker(struct snd_kcontrol *kcontrol,
     241                 :            :                                         struct snd_ctl_elem_info *uinfo)
     242                 :            : {
     243                 :            :         static char *texts[3] = {
     244                 :            :                 "Standard", "Small", "Smaller"
     245                 :            :         };
     246                 :            : 
     247                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
     248                 :          0 :         uinfo->count = 1;
     249                 :          0 :         uinfo->value.enumerated.items = 3;
     250         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 2)
     251                 :          0 :                 uinfo->value.enumerated.item = 2;
     252                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
     253                 :          0 :         return 0;
     254                 :            : }
     255                 :            : 
     256                 :          0 : static int snd_ac97_ymf7x3_get_speaker(struct snd_kcontrol *kcontrol,
     257                 :            :                                        struct snd_ctl_elem_value *ucontrol)
     258                 :            : {
     259                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     260                 :            :         unsigned short val;
     261                 :            : 
     262                 :          0 :         val = ac97->regs[AC97_YMF7X3_3D_MODE_SEL];
     263                 :          0 :         val = (val >> 10) & 3;
     264         [ #  # ]:          0 :         if (val > 0)    /* 0 = invalid */
     265                 :          0 :                 val--;
     266                 :          0 :         ucontrol->value.enumerated.item[0] = val;
     267                 :          0 :         return 0;
     268                 :            : }
     269                 :            : 
     270                 :          0 : static int snd_ac97_ymf7x3_put_speaker(struct snd_kcontrol *kcontrol,
     271                 :            :                                        struct snd_ctl_elem_value *ucontrol)
     272                 :            : {
     273                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     274                 :            :         unsigned short val;
     275                 :            : 
     276         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] > 2)
     277                 :            :                 return -EINVAL;
     278                 :          0 :         val = (ucontrol->value.enumerated.item[0] + 1) << 10;
     279                 :          0 :         return snd_ac97_update(ac97, AC97_YMF7X3_3D_MODE_SEL, val);
     280                 :            : }
     281                 :            : 
     282                 :            : static const struct snd_kcontrol_new snd_ac97_ymf7x3_controls_speaker =
     283                 :            : {
     284                 :            :         .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
     285                 :            :         .name   = "3D Control - Speaker",
     286                 :            :         .info   = snd_ac97_ymf7x3_info_speaker,
     287                 :            :         .get    = snd_ac97_ymf7x3_get_speaker,
     288                 :            :         .put    = snd_ac97_ymf7x3_put_speaker,
     289                 :            : };
     290                 :            : 
     291                 :            : /* It is possible to indicate to the Yamaha YMF7x3 the source to
     292                 :            :    direct to the S/PDIF output. */
     293                 :          0 : static int snd_ac97_ymf7x3_spdif_source_info(struct snd_kcontrol *kcontrol,
     294                 :            :                                              struct snd_ctl_elem_info *uinfo)
     295                 :            : {
     296                 :            :         static char *texts[2] = { "AC-Link", "A/D Converter" };
     297                 :            : 
     298                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
     299                 :          0 :         uinfo->count = 1;
     300                 :          0 :         uinfo->value.enumerated.items = 2;
     301         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 1)
     302                 :          0 :                 uinfo->value.enumerated.item = 1;
     303                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
     304                 :          0 :         return 0;
     305                 :            : }
     306                 :            : 
     307                 :          0 : static int snd_ac97_ymf7x3_spdif_source_get(struct snd_kcontrol *kcontrol,
     308                 :            :                                             struct snd_ctl_elem_value *ucontrol)
     309                 :            : {
     310                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     311                 :            :         unsigned short val;
     312                 :            : 
     313                 :          0 :         val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
     314                 :          0 :         ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
     315                 :          0 :         return 0;
     316                 :            : }
     317                 :            : 
     318                 :          0 : static int snd_ac97_ymf7x3_spdif_source_put(struct snd_kcontrol *kcontrol,
     319                 :            :                                             struct snd_ctl_elem_value *ucontrol)
     320                 :            : {
     321                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     322                 :            :         unsigned short val;
     323                 :            : 
     324         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] > 1)
     325                 :            :                 return -EINVAL;
     326                 :          0 :         val = ucontrol->value.enumerated.item[0] << 1;
     327                 :          0 :         return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0002, val);
     328                 :            : }
     329                 :            : 
     330                 :          0 : static int patch_yamaha_ymf7x3_3d(struct snd_ac97 *ac97)
     331                 :            : {
     332                 :            :         struct snd_kcontrol *kctl;
     333                 :            :         int err;
     334                 :            : 
     335                 :          0 :         kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97);
     336                 :          0 :         err = snd_ctl_add(ac97->bus->card, kctl);
     337         [ #  # ]:          0 :         if (err < 0)
     338                 :            :                 return err;
     339                 :          0 :         strcpy(kctl->id.name, "3D Control - Wide");
     340                 :          0 :         kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
     341                 :          0 :         snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
     342                 :          0 :         err = snd_ctl_add(ac97->bus->card,
     343                 :            :                           snd_ac97_cnew(&snd_ac97_ymf7x3_controls_speaker,
     344                 :            :                                         ac97));
     345         [ #  # ]:          0 :         if (err < 0)
     346                 :            :                 return err;
     347                 :          0 :         snd_ac97_write_cache(ac97, AC97_YMF7X3_3D_MODE_SEL, 0x0c00);
     348                 :          0 :         return 0;
     349                 :            : }
     350                 :            : 
     351                 :            : static const struct snd_kcontrol_new snd_ac97_yamaha_ymf743_controls_spdif[3] =
     352                 :            : {
     353                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
     354                 :            :                     AC97_YMF7X3_DIT_CTRL, 0, 1, 0),
     355                 :            :         {
     356                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
     357                 :            :                 .name   = SNDRV_CTL_NAME_IEC958("", PLAYBACK, NONE) "Source",
     358                 :            :                 .info   = snd_ac97_ymf7x3_spdif_source_info,
     359                 :            :                 .get    = snd_ac97_ymf7x3_spdif_source_get,
     360                 :            :                 .put    = snd_ac97_ymf7x3_spdif_source_put,
     361                 :            :         },
     362                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
     363                 :            :                     AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
     364                 :            : };
     365                 :            : 
     366                 :          0 : static int patch_yamaha_ymf743_build_spdif(struct snd_ac97 *ac97)
     367                 :            : {
     368                 :            :         int err;
     369                 :            : 
     370                 :          0 :         err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3);
     371         [ #  # ]:          0 :         if (err < 0)
     372                 :            :                 return err;
     373                 :          0 :         err = patch_build_controls(ac97,
     374                 :            :                                    snd_ac97_yamaha_ymf743_controls_spdif, 3);
     375         [ #  # ]:          0 :         if (err < 0)
     376                 :            :                 return err;
     377                 :            :         /* set default PCM S/PDIF params */
     378                 :            :         /* PCM audio,no copyright,no preemphasis,PCM coder,original */
     379                 :          0 :         snd_ac97_write_cache(ac97, AC97_YMF7X3_DIT_CTRL, 0xa201);
     380                 :          0 :         return 0;
     381                 :            : }
     382                 :            : 
     383                 :            : static const struct snd_ac97_build_ops patch_yamaha_ymf743_ops = {
     384                 :            :         .build_spdif    = patch_yamaha_ymf743_build_spdif,
     385                 :            :         .build_3d       = patch_yamaha_ymf7x3_3d,
     386                 :            : };
     387                 :            : 
     388                 :          0 : static int patch_yamaha_ymf743(struct snd_ac97 *ac97)
     389                 :            : {
     390                 :          0 :         ac97->build_ops = &patch_yamaha_ymf743_ops;
     391                 :          0 :         ac97->caps |= AC97_BC_BASS_TREBLE;
     392                 :          0 :         ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
     393                 :          0 :         ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
     394                 :          0 :         ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
     395                 :          0 :         return 0;
     396                 :            : }
     397                 :            : 
     398                 :            : /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
     399                 :            :    The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.
     400                 :            :    By default, no output pin is selected, and the S/PDIF signal is not output.
     401                 :            :    There is also a bit to mute S/PDIF output in a vendor-specific register. */
     402                 :          0 : static int snd_ac97_ymf753_spdif_output_pin_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
     403                 :            : {
     404                 :            :         static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };
     405                 :            : 
     406                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
     407                 :          0 :         uinfo->count = 1;
     408                 :          0 :         uinfo->value.enumerated.items = 3;
     409         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 2)
     410                 :          0 :                 uinfo->value.enumerated.item = 2;
     411                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
     412                 :          0 :         return 0;
     413                 :            : }
     414                 :            : 
     415                 :          0 : static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     416                 :            : {
     417                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     418                 :            :         unsigned short val;
     419                 :            : 
     420                 :          0 :         val = ac97->regs[AC97_YMF7X3_DIT_CTRL];
     421         [ #  # ]:          0 :         ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
     422                 :          0 :         return 0;
     423                 :            : }
     424                 :            : 
     425                 :          0 : static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
     426                 :            : {
     427                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
     428                 :            :         unsigned short val;
     429                 :            : 
     430         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] > 2)
     431                 :            :                 return -EINVAL;
     432 [ #  # ][ #  # ]:          0 :         val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
     433                 :            :               (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
     434                 :          0 :         return snd_ac97_update_bits(ac97, AC97_YMF7X3_DIT_CTRL, 0x0028, val);
     435                 :            :         /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
     436                 :            :            snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
     437                 :            : }
     438                 :            : 
     439                 :            : static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = {
     440                 :            :         {
     441                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
     442                 :            :                 .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
     443                 :            :                 .info   = snd_ac97_ymf7x3_spdif_source_info,
     444                 :            :                 .get    = snd_ac97_ymf7x3_spdif_source_get,
     445                 :            :                 .put    = snd_ac97_ymf7x3_spdif_source_put,
     446                 :            :         },
     447                 :            :         {
     448                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
     449                 :            :                 .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
     450                 :            :                 .info   = snd_ac97_ymf753_spdif_output_pin_info,
     451                 :            :                 .get    = snd_ac97_ymf753_spdif_output_pin_get,
     452                 :            :                 .put    = snd_ac97_ymf753_spdif_output_pin_put,
     453                 :            :         },
     454                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("", NONE, NONE) "Mute",
     455                 :            :                     AC97_YMF7X3_DIT_CTRL, 2, 1, 1)
     456                 :            : };
     457                 :            : 
     458                 :          0 : static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97)
     459                 :            : {
     460                 :            :         int err;
     461                 :            : 
     462         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif))) < 0)
     463                 :          0 :                 return err;
     464                 :            :         return 0;
     465                 :            : }
     466                 :            : 
     467                 :            : static const struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
     468                 :            :         .build_3d       = patch_yamaha_ymf7x3_3d,
     469                 :            :         .build_post_spdif = patch_yamaha_ymf753_post_spdif
     470                 :            : };
     471                 :            : 
     472                 :          0 : static int patch_yamaha_ymf753(struct snd_ac97 * ac97)
     473                 :            : {
     474                 :            :         /* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.
     475                 :            :            This chip has nonstandard and extended behaviour with regard to its S/PDIF output.
     476                 :            :            The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
     477                 :            :            The YMF753 will ouput the S/PDIF signal to pin 43, 47 (EAPD), or 48.
     478                 :            :            By default, no output pin is selected, and the S/PDIF signal is not output.
     479                 :            :            There is also a bit to mute S/PDIF output in a vendor-specific register.
     480                 :            :         */
     481                 :          0 :         ac97->build_ops = &patch_yamaha_ymf753_ops;
     482                 :          0 :         ac97->caps |= AC97_BC_BASS_TREBLE;
     483                 :          0 :         ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
     484                 :          0 :         return 0;
     485                 :            : }
     486                 :            : 
     487                 :            : /*
     488                 :            :  * May 2, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
     489                 :            :  *  removed broken wolfson00 patch.
     490                 :            :  *  added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
     491                 :            :  */
     492                 :            : 
     493                 :            : static const struct snd_kcontrol_new wm97xx_snd_ac97_controls[] = {
     494                 :            : AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
     495                 :            : AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
     496                 :            : };
     497                 :            : 
     498                 :          0 : static int patch_wolfson_wm9703_specific(struct snd_ac97 * ac97)
     499                 :            : {
     500                 :            :         /* This is known to work for the ViewSonic ViewPad 1000
     501                 :            :          * Randolph Bentson <bentson@holmsjoen.com>
     502                 :            :          * WM9703/9707/9708/9717 
     503                 :            :          */
     504                 :            :         int err, i;
     505                 :            :         
     506         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
     507         [ #  # ]:          0 :                 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0)
     508                 :            :                         return err;
     509                 :            :         }
     510                 :          0 :         snd_ac97_write_cache(ac97,  AC97_WM97XX_FMIXER_VOL, 0x0808);
     511                 :          0 :         return 0;
     512                 :            : }
     513                 :            : 
     514                 :            : static const struct snd_ac97_build_ops patch_wolfson_wm9703_ops = {
     515                 :            :         .build_specific = patch_wolfson_wm9703_specific,
     516                 :            : };
     517                 :            : 
     518                 :          0 : static int patch_wolfson03(struct snd_ac97 * ac97)
     519                 :            : {
     520                 :          0 :         ac97->build_ops = &patch_wolfson_wm9703_ops;
     521                 :          0 :         return 0;
     522                 :            : }
     523                 :            : 
     524                 :            : static const struct snd_kcontrol_new wm9704_snd_ac97_controls[] = {
     525                 :            : AC97_DOUBLE("Front Playback Volume", AC97_WM97XX_FMIXER_VOL, 8, 0, 31, 1),
     526                 :            : AC97_SINGLE("Front Playback Switch", AC97_WM97XX_FMIXER_VOL, 15, 1, 1),
     527                 :            : AC97_DOUBLE("Rear Playback Volume", AC97_WM9704_RMIXER_VOL, 8, 0, 31, 1),
     528                 :            : AC97_SINGLE("Rear Playback Switch", AC97_WM9704_RMIXER_VOL, 15, 1, 1),
     529                 :            : AC97_DOUBLE("Rear DAC Volume", AC97_WM9704_RPCM_VOL, 8, 0, 31, 1),
     530                 :            : AC97_DOUBLE("Surround Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
     531                 :            : };
     532                 :            : 
     533                 :          0 : static int patch_wolfson_wm9704_specific(struct snd_ac97 * ac97)
     534                 :            : {
     535                 :            :         int err, i;
     536         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) {
     537         [ #  # ]:          0 :                 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97))) < 0)
     538                 :            :                         return err;
     539                 :            :         }
     540                 :            :         /* patch for DVD noise */
     541                 :          0 :         snd_ac97_write_cache(ac97, AC97_WM9704_TEST, 0x0200);
     542                 :          0 :         return 0;
     543                 :            : }
     544                 :            : 
     545                 :            : static const struct snd_ac97_build_ops patch_wolfson_wm9704_ops = {
     546                 :            :         .build_specific = patch_wolfson_wm9704_specific,
     547                 :            : };
     548                 :            : 
     549                 :          0 : static int patch_wolfson04(struct snd_ac97 * ac97)
     550                 :            : {
     551                 :            :         /* WM9704M/9704Q */
     552                 :          0 :         ac97->build_ops = &patch_wolfson_wm9704_ops;
     553                 :          0 :         return 0;
     554                 :            : }
     555                 :            : 
     556                 :          0 : static int patch_wolfson05(struct snd_ac97 * ac97)
     557                 :            : {
     558                 :            :         /* WM9705, WM9710 */
     559                 :          0 :         ac97->build_ops = &patch_wolfson_wm9703_ops;
     560                 :            : #ifdef CONFIG_TOUCHSCREEN_WM9705
     561                 :            :         /* WM9705 touchscreen uses AUX and VIDEO for touch */
     562                 :            :         ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX;
     563                 :            : #endif
     564                 :          0 :         return 0;
     565                 :            : }
     566                 :            : 
     567                 :            : static const char* wm9711_alc_select[] = {"None", "Left", "Right", "Stereo"};
     568                 :            : static const char* wm9711_alc_mix[] = {"Stereo", "Right", "Left", "None"};
     569                 :            : static const char* wm9711_out3_src[] = {"Left", "VREF", "Left + Right", "Mono"};
     570                 :            : static const char* wm9711_out3_lrsrc[] = {"Master Mix", "Headphone Mix"};
     571                 :            : static const char* wm9711_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
     572                 :            : static const char* wm9711_base[] = {"Linear Control", "Adaptive Boost"};
     573                 :            : static const char* wm9711_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
     574                 :            : static const char* wm9711_mic[] = {"Mic 1", "Differential", "Mic 2", "Stereo"};
     575                 :            : static const char* wm9711_rec_sel[] = 
     576                 :            :         {"Mic 1", "NC", "NC", "Master Mix", "Line", "Headphone Mix", "Phone Mix", "Phone"};
     577                 :            : static const char* wm9711_ng_type[] = {"Constant Gain", "Mute"};
     578                 :            : 
     579                 :            : static const struct ac97_enum wm9711_enum[] = {
     580                 :            : AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9711_alc_select),
     581                 :            : AC97_ENUM_SINGLE(AC97_VIDEO, 10, 4, wm9711_alc_mix),
     582                 :            : AC97_ENUM_SINGLE(AC97_AUX, 9, 4, wm9711_out3_src),
     583                 :            : AC97_ENUM_SINGLE(AC97_AUX, 8, 2, wm9711_out3_lrsrc),
     584                 :            : AC97_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9711_rec_adc),
     585                 :            : AC97_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9711_base),
     586                 :            : AC97_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9711_rec_gain),
     587                 :            : AC97_ENUM_SINGLE(AC97_MIC, 5, 4, wm9711_mic),
     588                 :            : AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, wm9711_rec_sel),
     589                 :            : AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9711_ng_type),
     590                 :            : };
     591                 :            : 
     592                 :            : static const struct snd_kcontrol_new wm9711_snd_ac97_controls[] = {
     593                 :            : AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
     594                 :            : AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
     595                 :            : AC97_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
     596                 :            : AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
     597                 :            : AC97_ENUM("ALC Function", wm9711_enum[0]),
     598                 :            : AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 1),
     599                 :            : AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
     600                 :            : AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
     601                 :            : AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
     602                 :            : AC97_ENUM("ALC NG Type", wm9711_enum[9]),
     603                 :            : AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
     604                 :            : 
     605                 :            : AC97_SINGLE("Side Tone Switch", AC97_VIDEO, 15, 1, 1),
     606                 :            : AC97_SINGLE("Side Tone Volume", AC97_VIDEO, 12, 7, 1),
     607                 :            : AC97_ENUM("ALC Headphone Mux", wm9711_enum[1]),
     608                 :            : AC97_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
     609                 :            : 
     610                 :            : AC97_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
     611                 :            : AC97_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 0),
     612                 :            : AC97_ENUM("Out3 Mux", wm9711_enum[2]),
     613                 :            : AC97_ENUM("Out3 LR Mux", wm9711_enum[3]),
     614                 :            : AC97_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
     615                 :            : 
     616                 :            : AC97_SINGLE("Beep to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
     617                 :            : AC97_SINGLE("Beep to Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
     618                 :            : AC97_SINGLE("Beep to Side Tone Switch", AC97_PC_BEEP, 11, 1, 1),
     619                 :            : AC97_SINGLE("Beep to Side Tone Volume", AC97_PC_BEEP, 8, 7, 1),
     620                 :            : AC97_SINGLE("Beep to Phone Switch", AC97_PC_BEEP, 7, 1, 1),
     621                 :            : AC97_SINGLE("Beep to Phone Volume", AC97_PC_BEEP, 4, 7, 1),
     622                 :            : 
     623                 :            : AC97_SINGLE("Aux to Headphone Switch", AC97_CD, 15, 1, 1),
     624                 :            : AC97_SINGLE("Aux to Headphone Volume", AC97_CD, 12, 7, 1),
     625                 :            : AC97_SINGLE("Aux to Side Tone Switch", AC97_CD, 11, 1, 1),
     626                 :            : AC97_SINGLE("Aux to Side Tone Volume", AC97_CD, 8, 7, 1),
     627                 :            : AC97_SINGLE("Aux to Phone Switch", AC97_CD, 7, 1, 1),
     628                 :            : AC97_SINGLE("Aux to Phone Volume", AC97_CD, 4, 7, 1),
     629                 :            : 
     630                 :            : AC97_SINGLE("Phone to Headphone Switch", AC97_PHONE, 15, 1, 1),
     631                 :            : AC97_SINGLE("Phone to Master Switch", AC97_PHONE, 14, 1, 1),
     632                 :            : 
     633                 :            : AC97_SINGLE("Line to Headphone Switch", AC97_LINE, 15, 1, 1),
     634                 :            : AC97_SINGLE("Line to Master Switch", AC97_LINE, 14, 1, 1),
     635                 :            : AC97_SINGLE("Line to Phone Switch", AC97_LINE, 13, 1, 1),
     636                 :            : 
     637                 :            : AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PCM, 15, 1, 1),
     638                 :            : AC97_SINGLE("PCM Playback to Master Switch", AC97_PCM, 14, 1, 1),
     639                 :            : AC97_SINGLE("PCM Playback to Phone Switch", AC97_PCM, 13, 1, 1),
     640                 :            : 
     641                 :            : AC97_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
     642                 :            : AC97_ENUM("Capture to Phone Mux", wm9711_enum[4]),
     643                 :            : AC97_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
     644                 :            : AC97_ENUM("Capture Select", wm9711_enum[8]),
     645                 :            : 
     646                 :            : AC97_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
     647                 :            : AC97_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
     648                 :            : 
     649                 :            : AC97_ENUM("Bass Control", wm9711_enum[5]),
     650                 :            : AC97_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
     651                 :            : AC97_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
     652                 :            : AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
     653                 :            : 
     654                 :            : AC97_SINGLE("ADC Switch", AC97_REC_GAIN, 15, 1, 1),
     655                 :            : AC97_ENUM("Capture Volume Steps", wm9711_enum[6]),
     656                 :            : AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
     657                 :            : AC97_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
     658                 :            : 
     659                 :            : AC97_SINGLE("Mic 1 to Phone Switch", AC97_MIC, 14, 1, 1),
     660                 :            : AC97_SINGLE("Mic 2 to Phone Switch", AC97_MIC, 13, 1, 1),
     661                 :            : AC97_ENUM("Mic Select Source", wm9711_enum[7]),
     662                 :            : AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
     663                 :            : AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
     664                 :            : AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
     665                 :            : 
     666                 :            : AC97_SINGLE("Master Left Inv Switch", AC97_MASTER, 6, 1, 0),
     667                 :            : AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
     668                 :            : AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0),
     669                 :            : AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
     670                 :            : };
     671                 :            : 
     672                 :          0 : static int patch_wolfson_wm9711_specific(struct snd_ac97 * ac97)
     673                 :            : {
     674                 :            :         int err, i;
     675                 :            :         
     676         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(wm9711_snd_ac97_controls); i++) {
     677         [ #  # ]:          0 :                 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97))) < 0)
     678                 :            :                         return err;
     679                 :            :         }
     680                 :          0 :         snd_ac97_write_cache(ac97,  AC97_CODEC_CLASS_REV, 0x0808);
     681                 :          0 :         snd_ac97_write_cache(ac97,  AC97_PCI_SVID, 0x0808);
     682                 :          0 :         snd_ac97_write_cache(ac97,  AC97_VIDEO, 0x0808);
     683                 :          0 :         snd_ac97_write_cache(ac97,  AC97_AUX, 0x0808);
     684                 :          0 :         snd_ac97_write_cache(ac97,  AC97_PC_BEEP, 0x0808);
     685                 :          0 :         snd_ac97_write_cache(ac97,  AC97_CD, 0x0000);
     686                 :          0 :         return 0;
     687                 :            : }
     688                 :            : 
     689                 :            : static const struct snd_ac97_build_ops patch_wolfson_wm9711_ops = {
     690                 :            :         .build_specific = patch_wolfson_wm9711_specific,
     691                 :            : };
     692                 :            : 
     693                 :          0 : static int patch_wolfson11(struct snd_ac97 * ac97)
     694                 :            : {
     695                 :            :         /* WM9711, WM9712 */
     696                 :          0 :         ac97->build_ops = &patch_wolfson_wm9711_ops;
     697                 :            : 
     698                 :          0 :         ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_MIC |
     699                 :            :                 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
     700                 :            :         
     701                 :          0 :         return 0;
     702                 :            : }
     703                 :            : 
     704                 :            : static const char* wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
     705                 :            : static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
     706                 :            : static const char* wm9713_rec_src[] = 
     707                 :            :         {"Mic 1", "Mic 2", "Line", "Mono In", "Headphone Mix", "Master Mix", 
     708                 :            :         "Mono Mix", "Zh"};
     709                 :            : static const char* wm9713_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
     710                 :            : static const char* wm9713_alc_select[] = {"None", "Left", "Right", "Stereo"};
     711                 :            : static const char* wm9713_mono_pga[] = {"Vmid", "Zh", "Mono Mix", "Inv 1"};
     712                 :            : static const char* wm9713_spk_pga[] = 
     713                 :            :         {"Vmid", "Zh", "Headphone Mix", "Master Mix", "Inv", "NC", "NC", "NC"};
     714                 :            : static const char* wm9713_hp_pga[] = {"Vmid", "Zh", "Headphone Mix", "NC"};
     715                 :            : static const char* wm9713_out3_pga[] = {"Vmid", "Zh", "Inv 1", "NC"};
     716                 :            : static const char* wm9713_out4_pga[] = {"Vmid", "Zh", "Inv 2", "NC"};
     717                 :            : static const char* wm9713_dac_inv[] = 
     718                 :            :         {"Off", "Mono Mix", "Master Mix", "Headphone Mix L", "Headphone Mix R", 
     719                 :            :         "Headphone Mix Mono", "NC", "Vmid"};
     720                 :            : static const char* wm9713_base[] = {"Linear Control", "Adaptive Boost"};
     721                 :            : static const char* wm9713_ng_type[] = {"Constant Gain", "Mute"};
     722                 :            : 
     723                 :            : static const struct ac97_enum wm9713_enum[] = {
     724                 :            : AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer),
     725                 :            : AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux),
     726                 :            : AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),
     727                 :            : AC97_ENUM_DOUBLE(AC97_VIDEO, 3, 0, 8, wm9713_rec_src),
     728                 :            : AC97_ENUM_DOUBLE(AC97_CD, 14, 6, 2, wm9713_rec_gain),
     729                 :            : AC97_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9713_alc_select),
     730                 :            : AC97_ENUM_SINGLE(AC97_REC_GAIN, 14, 4, wm9713_mono_pga),
     731                 :            : AC97_ENUM_DOUBLE(AC97_REC_GAIN, 11, 8, 8, wm9713_spk_pga),
     732                 :            : AC97_ENUM_DOUBLE(AC97_REC_GAIN, 6, 4, 4, wm9713_hp_pga),
     733                 :            : AC97_ENUM_SINGLE(AC97_REC_GAIN, 2, 4, wm9713_out3_pga),
     734                 :            : AC97_ENUM_SINGLE(AC97_REC_GAIN, 0, 4, wm9713_out4_pga),
     735                 :            : AC97_ENUM_DOUBLE(AC97_REC_GAIN_MIC, 13, 10, 8, wm9713_dac_inv),
     736                 :            : AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_base),
     737                 :            : AC97_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type),
     738                 :            : };
     739                 :            : 
     740                 :            : static const struct snd_kcontrol_new wm13_snd_ac97_controls[] = {
     741                 :            : AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
     742                 :            : AC97_SINGLE("Line In to Headphone Switch", AC97_PC_BEEP, 15, 1, 1),
     743                 :            : AC97_SINGLE("Line In to Master Switch", AC97_PC_BEEP, 14, 1, 1),
     744                 :            : AC97_SINGLE("Line In to Mono Switch", AC97_PC_BEEP, 13, 1, 1),
     745                 :            : 
     746                 :            : AC97_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),
     747                 :            : AC97_SINGLE("PCM Playback to Headphone Switch", AC97_PHONE, 15, 1, 1),
     748                 :            : AC97_SINGLE("PCM Playback to Master Switch", AC97_PHONE, 14, 1, 1),
     749                 :            : AC97_SINGLE("PCM Playback to Mono Switch", AC97_PHONE, 13, 1, 1),
     750                 :            : 
     751                 :            : AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
     752                 :            : AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
     753                 :            : AC97_SINGLE("Mic 1 to Mono Switch", AC97_LINE, 7, 1, 1),
     754                 :            : AC97_SINGLE("Mic 2 to Mono Switch", AC97_LINE, 6, 1, 1),
     755                 :            : AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_LINE, 5, 1, 0),
     756                 :            : AC97_ENUM("Mic to Headphone Mux", wm9713_enum[0]),
     757                 :            : AC97_SINGLE("Mic Headphone Mixer Volume", AC97_LINE, 0, 7, 1),
     758                 :            : 
     759                 :            : AC97_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),
     760                 :            : AC97_ENUM("Capture Volume Steps", wm9713_enum[4]),
     761                 :            : AC97_DOUBLE("Capture Volume", AC97_CD, 8, 0, 15, 0),
     762                 :            : AC97_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),
     763                 :            : 
     764                 :            : AC97_ENUM("Capture to Headphone Mux", wm9713_enum[1]),
     765                 :            : AC97_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),
     766                 :            : AC97_ENUM("Capture to Mono Mux", wm9713_enum[2]),
     767                 :            : AC97_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),
     768                 :            : AC97_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),
     769                 :            : AC97_ENUM("Capture Select", wm9713_enum[3]),
     770                 :            : 
     771                 :            : AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
     772                 :            : AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
     773                 :            : AC97_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),
     774                 :            : AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
     775                 :            : AC97_ENUM("ALC Function", wm9713_enum[5]),
     776                 :            : AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
     777                 :            : AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),
     778                 :            : AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
     779                 :            : AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
     780                 :            : AC97_ENUM("ALC NG Type", wm9713_enum[13]),
     781                 :            : AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),
     782                 :            : 
     783                 :            : AC97_DOUBLE("Master ZC Switch", AC97_MASTER, 14, 6, 1, 0),
     784                 :            : AC97_DOUBLE("Headphone ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),
     785                 :            : AC97_DOUBLE("Out3/4 ZC Switch", AC97_MASTER_MONO, 14, 6, 1, 0),
     786                 :            : AC97_SINGLE("Master Right Switch", AC97_MASTER, 7, 1, 1),
     787                 :            : AC97_SINGLE("Headphone Right Switch", AC97_HEADPHONE, 7, 1, 1),
     788                 :            : AC97_SINGLE("Out3/4 Right Switch", AC97_MASTER_MONO, 7, 1, 1),
     789                 :            : 
     790                 :            : AC97_SINGLE("Mono In to Headphone Switch", AC97_MASTER_TONE, 15, 1, 1),
     791                 :            : AC97_SINGLE("Mono In to Master Switch", AC97_MASTER_TONE, 14, 1, 1),
     792                 :            : AC97_SINGLE("Mono In Volume", AC97_MASTER_TONE, 8, 31, 1),
     793                 :            : AC97_SINGLE("Mono Switch", AC97_MASTER_TONE, 7, 1, 1),
     794                 :            : AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0),
     795                 :            : AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1),
     796                 :            : 
     797                 :            : AC97_SINGLE("Beep to Headphone Switch", AC97_AUX, 15, 1, 1),
     798                 :            : AC97_SINGLE("Beep to Headphone Volume", AC97_AUX, 12, 7, 1),
     799                 :            : AC97_SINGLE("Beep to Master Switch", AC97_AUX, 11, 1, 1),
     800                 :            : AC97_SINGLE("Beep to Master Volume", AC97_AUX, 8, 7, 1),
     801                 :            : AC97_SINGLE("Beep to Mono Switch", AC97_AUX, 7, 1, 1),
     802                 :            : AC97_SINGLE("Beep to Mono Volume", AC97_AUX, 4, 7, 1),
     803                 :            : 
     804                 :            : AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1),
     805                 :            : AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1),
     806                 :            : AC97_SINGLE("Voice to Master Switch", AC97_PCM, 11, 1, 1),
     807                 :            : AC97_SINGLE("Voice to Master Volume", AC97_PCM, 8, 7, 1),
     808                 :            : AC97_SINGLE("Voice to Mono Switch", AC97_PCM, 7, 1, 1),
     809                 :            : AC97_SINGLE("Voice to Mono Volume", AC97_PCM, 4, 7, 1),
     810                 :            : 
     811                 :            : AC97_SINGLE("Aux to Headphone Switch", AC97_REC_SEL, 15, 1, 1),
     812                 :            : AC97_SINGLE("Aux to Headphone Volume", AC97_REC_SEL, 12, 7, 1),
     813                 :            : AC97_SINGLE("Aux to Master Switch", AC97_REC_SEL, 11, 1, 1),
     814                 :            : AC97_SINGLE("Aux to Master Volume", AC97_REC_SEL, 8, 7, 1),
     815                 :            : AC97_SINGLE("Aux to Mono Switch", AC97_REC_SEL, 7, 1, 1),
     816                 :            : AC97_SINGLE("Aux to Mono Volume", AC97_REC_SEL, 4, 7, 1),
     817                 :            : 
     818                 :            : AC97_ENUM("Mono Input Mux", wm9713_enum[6]),
     819                 :            : AC97_ENUM("Master Input Mux", wm9713_enum[7]),
     820                 :            : AC97_ENUM("Headphone Input Mux", wm9713_enum[8]),
     821                 :            : AC97_ENUM("Out 3 Input Mux", wm9713_enum[9]),
     822                 :            : AC97_ENUM("Out 4 Input Mux", wm9713_enum[10]),
     823                 :            : 
     824                 :            : AC97_ENUM("Bass Control", wm9713_enum[12]),
     825                 :            : AC97_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),
     826                 :            : AC97_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),
     827                 :            : AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),
     828                 :            : AC97_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),
     829                 :            : AC97_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),
     830                 :            : };
     831                 :            : 
     832                 :            : static const struct snd_kcontrol_new wm13_snd_ac97_controls_3d[] = {
     833                 :            : AC97_ENUM("Inv Input Mux", wm9713_enum[11]),
     834                 :            : AC97_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),
     835                 :            : AC97_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
     836                 :            : AC97_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
     837                 :            : };
     838                 :            : 
     839                 :          0 : static int patch_wolfson_wm9713_3d (struct snd_ac97 * ac97)
     840                 :            : {
     841                 :            :         int err, i;
     842                 :            :     
     843         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) {
     844         [ #  # ]:          0 :                 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97))) < 0)
     845                 :            :                         return err;
     846                 :            :         }
     847                 :            :         return 0;
     848                 :            : }
     849                 :            : 
     850                 :          0 : static int patch_wolfson_wm9713_specific(struct snd_ac97 * ac97)
     851                 :            : {
     852                 :            :         int err, i;
     853                 :            :         
     854         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) {
     855         [ #  # ]:          0 :                 if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97))) < 0)
     856                 :            :                         return err;
     857                 :            :         }
     858                 :          0 :         snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
     859                 :          0 :         snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808);
     860                 :          0 :         snd_ac97_write_cache(ac97, AC97_MIC, 0x0808);
     861                 :          0 :         snd_ac97_write_cache(ac97, AC97_LINE, 0x00da);
     862                 :          0 :         snd_ac97_write_cache(ac97, AC97_CD, 0x0808);
     863                 :          0 :         snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612);
     864                 :          0 :         snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0);
     865                 :          0 :         return 0;
     866                 :            : }
     867                 :            : 
     868                 :            : #ifdef CONFIG_PM
     869                 :          0 : static void patch_wolfson_wm9713_suspend (struct snd_ac97 * ac97)
     870                 :            : {
     871                 :          0 :         snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff);
     872                 :          0 :         snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff);
     873                 :          0 : }
     874                 :            : 
     875                 :          0 : static void patch_wolfson_wm9713_resume (struct snd_ac97 * ac97)
     876                 :            : {
     877                 :          0 :         snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
     878                 :          0 :         snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
     879                 :          0 :         snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
     880                 :          0 : }
     881                 :            : #endif
     882                 :            : 
     883                 :            : static const struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
     884                 :            :         .build_specific = patch_wolfson_wm9713_specific,
     885                 :            :         .build_3d = patch_wolfson_wm9713_3d,
     886                 :            : #ifdef CONFIG_PM        
     887                 :            :         .suspend = patch_wolfson_wm9713_suspend,
     888                 :            :         .resume = patch_wolfson_wm9713_resume
     889                 :            : #endif
     890                 :            : };
     891                 :            : 
     892                 :          0 : static int patch_wolfson13(struct snd_ac97 * ac97)
     893                 :            : {
     894                 :            :         /* WM9713, WM9714 */
     895                 :          0 :         ac97->build_ops = &patch_wolfson_wm9713_ops;
     896                 :            : 
     897                 :          0 :         ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE |
     898                 :            :                 AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD | AC97_HAS_NO_TONE |
     899                 :            :                 AC97_HAS_NO_STD_PCM;
     900                 :          0 :         ac97->scaps &= ~AC97_SCAP_MODEM;
     901                 :            : 
     902                 :          0 :         snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
     903                 :          0 :         snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
     904                 :          0 :         snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
     905                 :            : 
     906                 :          0 :         return 0;
     907                 :            : }
     908                 :            : 
     909                 :            : /*
     910                 :            :  * Tritech codec
     911                 :            :  */
     912                 :          0 : static int patch_tritech_tr28028(struct snd_ac97 * ac97)
     913                 :            : {
     914                 :          0 :         snd_ac97_write_cache(ac97, 0x26, 0x0300);
     915                 :          0 :         snd_ac97_write_cache(ac97, 0x26, 0x0000);
     916                 :          0 :         snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000);
     917                 :          0 :         snd_ac97_write_cache(ac97, AC97_SPDIF, 0x0000);
     918                 :          0 :         return 0;
     919                 :            : }
     920                 :            : 
     921                 :            : /*
     922                 :            :  * Sigmatel STAC97xx codecs
     923                 :            :  */
     924                 :          0 : static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97)
     925                 :            : {
     926                 :            :         struct snd_kcontrol *kctl;
     927                 :            :         int err;
     928                 :            : 
     929         [ #  # ]:          0 :         if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
     930                 :            :                 return err;
     931                 :          0 :         strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
     932                 :          0 :         kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
     933                 :          0 :         snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
     934                 :          0 :         return 0;
     935                 :            : }
     936                 :            : 
     937                 :          0 : static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97)
     938                 :            : {
     939                 :            :         struct snd_kcontrol *kctl;
     940                 :            :         int err;
     941                 :            : 
     942         [ #  # ]:          0 :         if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
     943                 :            :                 return err;
     944                 :          0 :         strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
     945                 :          0 :         kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
     946         [ #  # ]:          0 :         if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
     947                 :            :                 return err;
     948                 :          0 :         strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
     949                 :          0 :         kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
     950                 :          0 :         snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
     951                 :          0 :         return 0;
     952                 :            : }
     953                 :            : 
     954                 :            : static const struct snd_kcontrol_new snd_ac97_sigmatel_4speaker =
     955                 :            : AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch",
     956                 :            :                 AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);
     957                 :            : 
     958                 :            : /* "Sigmatel " removed due to excessive name length: */
     959                 :            : static const struct snd_kcontrol_new snd_ac97_sigmatel_phaseinvert =
     960                 :            : AC97_SINGLE("Surround Phase Inversion Playback Switch",
     961                 :            :                 AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
     962                 :            : 
     963                 :            : static const struct snd_kcontrol_new snd_ac97_sigmatel_controls[] = {
     964                 :            : AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
     965                 :            : AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
     966                 :            : };
     967                 :            : 
     968                 :          0 : static int patch_sigmatel_stac97xx_specific(struct snd_ac97 * ac97)
     969                 :            : {
     970                 :            :         int err;
     971                 :            : 
     972                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
     973         [ #  # ]:          0 :         if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1))
     974         [ #  # ]:          0 :                 if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1)) < 0)
     975                 :            :                         return err;
     976         [ #  # ]:          0 :         if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
     977         [ #  # ]:          0 :                 if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1)) < 0)
     978                 :            :                         return err;
     979         [ #  # ]:          0 :         if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2))
     980         [ #  # ]:          0 :                 if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1)) < 0)
     981                 :            :                         return err;
     982         [ #  # ]:          0 :         if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3))
     983         [ #  # ]:          0 :                 if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1)) < 0)
     984                 :          0 :                         return err;
     985                 :            :         return 0;
     986                 :            : }
     987                 :            : 
     988                 :            : static const struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
     989                 :            :         .build_3d       = patch_sigmatel_stac9700_3d,
     990                 :            :         .build_specific = patch_sigmatel_stac97xx_specific
     991                 :            : };
     992                 :            : 
     993                 :          0 : static int patch_sigmatel_stac9700(struct snd_ac97 * ac97)
     994                 :            : {
     995                 :          0 :         ac97->build_ops = &patch_sigmatel_stac9700_ops;
     996                 :          0 :         return 0;
     997                 :            : }
     998                 :            : 
     999                 :          0 : static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1000                 :            : {
    1001                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1002                 :            :         int err;
    1003                 :            : 
    1004                 :          0 :         mutex_lock(&ac97->page_mutex);
    1005                 :          0 :         snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
    1006                 :          0 :         err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010,
    1007                 :          0 :                                    (ucontrol->value.integer.value[0] & 1) << 4);
    1008                 :          0 :         snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0);
    1009                 :          0 :         mutex_unlock(&ac97->page_mutex);
    1010                 :          0 :         return err;
    1011                 :            : }
    1012                 :            : 
    1013                 :            : static const struct snd_kcontrol_new snd_ac97_stac9708_bias_control = {
    1014                 :            :         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    1015                 :            :         .name = "Sigmatel Output Bias Switch",
    1016                 :            :         .info = snd_ac97_info_volsw,
    1017                 :            :         .get = snd_ac97_get_volsw,
    1018                 :            :         .put = snd_ac97_stac9708_put_bias,
    1019                 :            :         .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),
    1020                 :            : };
    1021                 :            : 
    1022                 :          0 : static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97)
    1023                 :            : {
    1024                 :            :         int err;
    1025                 :            : 
    1026                 :            :         /* the register bit is writable, but the function is not implemented: */
    1027                 :          0 :         snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL);
    1028                 :            : 
    1029                 :          0 :         snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
    1030         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0)
    1031                 :            :                 return err;
    1032                 :          0 :         return patch_sigmatel_stac97xx_specific(ac97);
    1033                 :            : }
    1034                 :            : 
    1035                 :            : static const struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
    1036                 :            :         .build_3d       = patch_sigmatel_stac9708_3d,
    1037                 :            :         .build_specific = patch_sigmatel_stac9708_specific
    1038                 :            : };
    1039                 :            : 
    1040                 :          0 : static int patch_sigmatel_stac9708(struct snd_ac97 * ac97)
    1041                 :            : {
    1042                 :            :         unsigned int codec72, codec6c;
    1043                 :            : 
    1044                 :          0 :         ac97->build_ops = &patch_sigmatel_stac9708_ops;
    1045                 :          0 :         ac97->caps |= 0x10;  /* HP (sigmatel surround) support */
    1046                 :            : 
    1047                 :          0 :         codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
    1048                 :          0 :         codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
    1049                 :            : 
    1050         [ #  # ]:          0 :         if ((codec72==0) && (codec6c==0)) {
    1051                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
    1052                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1000);
    1053                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
    1054                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0007);
    1055         [ #  # ]:          0 :         } else if ((codec72==0x8000) && (codec6c==0)) {
    1056                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
    1057                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1001);
    1058                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_DAC2INVERT, 0x0008);
    1059                 :            :         } else if ((codec72==0x8000) && (codec6c==0x0080)) {
    1060                 :            :                 /* nothing */
    1061                 :            :         }
    1062                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
    1063                 :          0 :         return 0;
    1064                 :            : }
    1065                 :            : 
    1066                 :          0 : static int patch_sigmatel_stac9721(struct snd_ac97 * ac97)
    1067                 :            : {
    1068                 :          0 :         ac97->build_ops = &patch_sigmatel_stac9700_ops;
    1069         [ #  # ]:          0 :         if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
    1070                 :            :                 // patch for SigmaTel
    1071                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
    1072                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x4000);
    1073                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
    1074                 :          0 :                 snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
    1075                 :            :         }
    1076                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
    1077                 :          0 :         return 0;
    1078                 :            : }
    1079                 :            : 
    1080                 :          0 : static int patch_sigmatel_stac9744(struct snd_ac97 * ac97)
    1081                 :            : {
    1082                 :            :         // patch for SigmaTel
    1083                 :          0 :         ac97->build_ops = &patch_sigmatel_stac9700_ops;
    1084                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
    1085                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
    1086                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
    1087                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
    1088                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
    1089                 :          0 :         return 0;
    1090                 :            : }
    1091                 :            : 
    1092                 :          0 : static int patch_sigmatel_stac9756(struct snd_ac97 * ac97)
    1093                 :            : {
    1094                 :            :         // patch for SigmaTel
    1095                 :          0 :         ac97->build_ops = &patch_sigmatel_stac9700_ops;
    1096                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
    1097                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
    1098                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
    1099                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002);
    1100                 :          0 :         snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000);
    1101                 :          0 :         return 0;
    1102                 :            : }
    1103                 :            : 
    1104                 :          0 : static int snd_ac97_stac9758_output_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    1105                 :            : {
    1106                 :            :         static char *texts[5] = { "Input/Disabled", "Front Output",
    1107                 :            :                 "Rear Output", "Center/LFE Output", "Mixer Output" };
    1108                 :            : 
    1109                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
    1110                 :          0 :         uinfo->count = 1;
    1111                 :          0 :         uinfo->value.enumerated.items = 5;
    1112         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 4)
    1113                 :          0 :                 uinfo->value.enumerated.item = 4;
    1114                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
    1115                 :          0 :         return 0;
    1116                 :            : }
    1117                 :            : 
    1118                 :          0 : static int snd_ac97_stac9758_output_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1119                 :            : {
    1120                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1121                 :          0 :         int shift = kcontrol->private_value;
    1122                 :            :         unsigned short val;
    1123                 :            : 
    1124                 :          0 :         val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
    1125         [ #  # ]:          0 :         if (!(val & 4))
    1126                 :          0 :                 ucontrol->value.enumerated.item[0] = 0;
    1127                 :            :         else
    1128                 :          0 :                 ucontrol->value.enumerated.item[0] = 1 + (val & 3);
    1129                 :          0 :         return 0;
    1130                 :            : }
    1131                 :            : 
    1132                 :          0 : static int snd_ac97_stac9758_output_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1133                 :            : {
    1134                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1135                 :          0 :         int shift = kcontrol->private_value;
    1136                 :            :         unsigned short val;
    1137                 :            : 
    1138         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] > 4)
    1139                 :            :                 return -EINVAL;
    1140         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] == 0)
    1141                 :            :                 val = 0;
    1142                 :            :         else
    1143                 :          0 :                 val = 4 | (ucontrol->value.enumerated.item[0] - 1);
    1144                 :          0 :         return ac97_update_bits_page(ac97, AC97_SIGMATEL_OUTSEL,
    1145                 :          0 :                                      7 << shift, val << shift, 0);
    1146                 :            : }
    1147                 :            : 
    1148                 :          0 : static int snd_ac97_stac9758_input_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    1149                 :            : {
    1150                 :            :         static char *texts[7] = { "Mic2 Jack", "Mic1 Jack", "Line In Jack",
    1151                 :            :                 "Front Jack", "Rear Jack", "Center/LFE Jack", "Mute" };
    1152                 :            : 
    1153                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
    1154                 :          0 :         uinfo->count = 1;
    1155                 :          0 :         uinfo->value.enumerated.items = 7;
    1156         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 6)
    1157                 :          0 :                 uinfo->value.enumerated.item = 6;
    1158                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
    1159                 :          0 :         return 0;
    1160                 :            : }
    1161                 :            : 
    1162                 :          0 : static int snd_ac97_stac9758_input_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1163                 :            : {
    1164                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1165                 :          0 :         int shift = kcontrol->private_value;
    1166                 :            :         unsigned short val;
    1167                 :            : 
    1168                 :          0 :         val = ac97->regs[AC97_SIGMATEL_INSEL];
    1169                 :          0 :         ucontrol->value.enumerated.item[0] = (val >> shift) & 7;
    1170                 :          0 :         return 0;
    1171                 :            : }
    1172                 :            : 
    1173                 :          0 : static int snd_ac97_stac9758_input_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1174                 :            : {
    1175                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1176                 :          0 :         int shift = kcontrol->private_value;
    1177                 :            : 
    1178                 :          0 :         return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
    1179                 :          0 :                                      ucontrol->value.enumerated.item[0] << shift, 0);
    1180                 :            : }
    1181                 :            : 
    1182                 :          0 : static int snd_ac97_stac9758_phonesel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    1183                 :            : {
    1184                 :            :         static char *texts[3] = { "None", "Front Jack", "Rear Jack" };
    1185                 :            : 
    1186                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
    1187                 :          0 :         uinfo->count = 1;
    1188                 :          0 :         uinfo->value.enumerated.items = 3;
    1189         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 2)
    1190                 :          0 :                 uinfo->value.enumerated.item = 2;
    1191                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
    1192                 :          0 :         return 0;
    1193                 :            : }
    1194                 :            : 
    1195                 :          0 : static int snd_ac97_stac9758_phonesel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1196                 :            : {
    1197                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1198                 :            : 
    1199                 :          0 :         ucontrol->value.enumerated.item[0] = ac97->regs[AC97_SIGMATEL_IOMISC] & 3;
    1200                 :          0 :         return 0;
    1201                 :            : }
    1202                 :            : 
    1203                 :          0 : static int snd_ac97_stac9758_phonesel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1204                 :            : {
    1205                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1206                 :            : 
    1207                 :          0 :         return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
    1208                 :          0 :                                      ucontrol->value.enumerated.item[0], 0);
    1209                 :            : }
    1210                 :            : 
    1211                 :            : #define STAC9758_OUTPUT_JACK(xname, shift) \
    1212                 :            : {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
    1213                 :            :         .info = snd_ac97_stac9758_output_jack_info, \
    1214                 :            :         .get = snd_ac97_stac9758_output_jack_get, \
    1215                 :            :         .put = snd_ac97_stac9758_output_jack_put, \
    1216                 :            :         .private_value = shift }
    1217                 :            : #define STAC9758_INPUT_JACK(xname, shift) \
    1218                 :            : {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
    1219                 :            :         .info = snd_ac97_stac9758_input_jack_info, \
    1220                 :            :         .get = snd_ac97_stac9758_input_jack_get, \
    1221                 :            :         .put = snd_ac97_stac9758_input_jack_put, \
    1222                 :            :         .private_value = shift }
    1223                 :            : static const struct snd_kcontrol_new snd_ac97_sigmatel_stac9758_controls[] = {
    1224                 :            :         STAC9758_OUTPUT_JACK("Mic1 Jack", 1),
    1225                 :            :         STAC9758_OUTPUT_JACK("LineIn Jack", 4),
    1226                 :            :         STAC9758_OUTPUT_JACK("Front Jack", 7),
    1227                 :            :         STAC9758_OUTPUT_JACK("Rear Jack", 10),
    1228                 :            :         STAC9758_OUTPUT_JACK("Center/LFE Jack", 13),
    1229                 :            :         STAC9758_INPUT_JACK("Mic Input Source", 0),
    1230                 :            :         STAC9758_INPUT_JACK("Line Input Source", 8),
    1231                 :            :         {
    1232                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    1233                 :            :                 .name = "Headphone Amp",
    1234                 :            :                 .info = snd_ac97_stac9758_phonesel_info,
    1235                 :            :                 .get = snd_ac97_stac9758_phonesel_get,
    1236                 :            :                 .put = snd_ac97_stac9758_phonesel_put
    1237                 :            :         },
    1238                 :            :         AC97_SINGLE("Exchange Center/LFE", AC97_SIGMATEL_IOMISC, 4, 1, 0),
    1239                 :            :         AC97_SINGLE("Headphone +3dB Boost", AC97_SIGMATEL_IOMISC, 8, 1, 0)
    1240                 :            : };
    1241                 :            : 
    1242                 :          0 : static int patch_sigmatel_stac9758_specific(struct snd_ac97 *ac97)
    1243                 :            : {
    1244                 :            :         int err;
    1245                 :            : 
    1246                 :          0 :         err = patch_sigmatel_stac97xx_specific(ac97);
    1247         [ #  # ]:          0 :         if (err < 0)
    1248                 :            :                 return err;
    1249                 :          0 :         err = patch_build_controls(ac97, snd_ac97_sigmatel_stac9758_controls,
    1250                 :            :                                    ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
    1251         [ #  # ]:          0 :         if (err < 0)
    1252                 :            :                 return err;
    1253                 :            :         /* DAC-A direct */
    1254                 :          0 :         snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
    1255                 :            :         /* DAC-A to Mix = PCM */
    1256                 :            :         /* DAC-B direct = Surround */
    1257                 :            :         /* DAC-B to Mix */
    1258                 :          0 :         snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
    1259                 :            :         /* DAC-C direct = Center/LFE */
    1260                 :            : 
    1261                 :          0 :         return 0;
    1262                 :            : }
    1263                 :            : 
    1264                 :            : static const struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = {
    1265                 :            :         .build_3d       = patch_sigmatel_stac9700_3d,
    1266                 :            :         .build_specific = patch_sigmatel_stac9758_specific
    1267                 :            : };
    1268                 :            : 
    1269                 :          0 : static int patch_sigmatel_stac9758(struct snd_ac97 * ac97)
    1270                 :            : {
    1271                 :            :         static unsigned short regs[4] = {
    1272                 :            :                 AC97_SIGMATEL_OUTSEL,
    1273                 :            :                 AC97_SIGMATEL_IOMISC,
    1274                 :            :                 AC97_SIGMATEL_INSEL,
    1275                 :            :                 AC97_SIGMATEL_VARIOUS
    1276                 :            :         };
    1277                 :            :         static unsigned short def_regs[4] = {
    1278                 :            :                 /* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
    1279                 :            :                 /* IOMISC */ 0x2001,
    1280                 :            :                 /* INSEL */ 0x0201, /* LI:LI, MI:M1 */
    1281                 :            :                 /* VARIOUS */ 0x0040
    1282                 :            :         };
    1283                 :            :         static unsigned short m675_regs[4] = {
    1284                 :            :                 /* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */
    1285                 :            :                 /* IOMISC */ 0x2102, /* HP amp on */
    1286                 :            :                 /* INSEL */ 0x0203, /* LI:LI, MI:FR */
    1287                 :            :                 /* VARIOUS */ 0x0041 /* stereo mic */
    1288                 :            :         };
    1289                 :            :         unsigned short *pregs = def_regs;
    1290                 :            :         int i;
    1291                 :            : 
    1292                 :            :         /* Gateway M675 notebook */
    1293         [ #  # ]:          0 :         if (ac97->pci && 
    1294         [ #  # ]:          0 :             ac97->subsystem_vendor == 0x107b &&
    1295                 :            :             ac97->subsystem_device == 0x0601)
    1296                 :            :                 pregs = m675_regs;
    1297                 :            : 
    1298                 :            :         // patch for SigmaTel
    1299                 :          0 :         ac97->build_ops = &patch_sigmatel_stac9758_ops;
    1300                 :            :         /* FIXME: assume only page 0 for writing cache */
    1301                 :          0 :         snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
    1302         [ #  # ]:          0 :         for (i = 0; i < 4; i++)
    1303                 :          0 :                 snd_ac97_write_cache(ac97, regs[i], pregs[i]);
    1304                 :            : 
    1305                 :          0 :         ac97->flags |= AC97_STEREO_MUTES;
    1306                 :          0 :         return 0;
    1307                 :            : }
    1308                 :            : 
    1309                 :            : /*
    1310                 :            :  * Cirrus Logic CS42xx codecs
    1311                 :            :  */
    1312                 :            : static const struct snd_kcontrol_new snd_ac97_cirrus_controls_spdif[2] = {
    1313                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
    1314                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
    1315                 :            : };
    1316                 :            : 
    1317                 :          0 : static int patch_cirrus_build_spdif(struct snd_ac97 * ac97)
    1318                 :            : {
    1319                 :            :         int err;
    1320                 :            : 
    1321                 :            :         /* con mask, pro mask, default */
    1322         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
    1323                 :            :                 return err;
    1324                 :            :         /* switch, spsa */
    1325         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0)
    1326                 :            :                 return err;
    1327         [ #  # ]:          0 :         switch (ac97->id & AC97_ID_CS_MASK) {
    1328                 :            :         case AC97_ID_CS4205:
    1329         [ #  # ]:          0 :                 if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1)) < 0)
    1330                 :            :                         return err;
    1331                 :            :                 break;
    1332                 :            :         }
    1333                 :            :         /* set default PCM S/PDIF params */
    1334                 :            :         /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
    1335                 :          0 :         snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
    1336                 :          0 :         return 0;
    1337                 :            : }
    1338                 :            : 
    1339                 :            : static const struct snd_ac97_build_ops patch_cirrus_ops = {
    1340                 :            :         .build_spdif = patch_cirrus_build_spdif
    1341                 :            : };
    1342                 :            : 
    1343                 :          0 : static int patch_cirrus_spdif(struct snd_ac97 * ac97)
    1344                 :            : {
    1345                 :            :         /* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
    1346                 :            :            WHY CAN'T ANYONE FOLLOW THE BLOODY SPEC?  *sigh*
    1347                 :            :            - sp/dif EA ID is not set, but sp/dif is always present.
    1348                 :            :            - enable/disable is spdif register bit 15.
    1349                 :            :            - sp/dif control register is 0x68.  differs from AC97:
    1350                 :            :            - valid is bit 14 (vs 15)
    1351                 :            :            - no DRS
    1352                 :            :            - only 44.1/48k [00 = 48, 01=44,1] (AC97 is 00=44.1, 10=48)
    1353                 :            :            - sp/dif ssource select is in 0x5e bits 0,1.
    1354                 :            :         */
    1355                 :            : 
    1356                 :          0 :         ac97->build_ops = &patch_cirrus_ops;
    1357                 :          0 :         ac97->flags |= AC97_CS_SPDIF; 
    1358                 :          0 :         ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
    1359                 :          0 :         ac97->ext_id |= AC97_EI_SPDIF;       /* force the detection of spdif */
    1360                 :          0 :         snd_ac97_write_cache(ac97, AC97_CSR_ACMODE, 0x0080);
    1361                 :          0 :         return 0;
    1362                 :            : }
    1363                 :            : 
    1364                 :          0 : static int patch_cirrus_cs4299(struct snd_ac97 * ac97)
    1365                 :            : {
    1366                 :            :         /* force the detection of PC Beep */
    1367                 :          0 :         ac97->flags |= AC97_HAS_PC_BEEP;
    1368                 :            :         
    1369                 :          0 :         return patch_cirrus_spdif(ac97);
    1370                 :            : }
    1371                 :            : 
    1372                 :            : /*
    1373                 :            :  * Conexant codecs
    1374                 :            :  */
    1375                 :            : static const struct snd_kcontrol_new snd_ac97_conexant_controls_spdif[1] = {
    1376                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
    1377                 :            : };
    1378                 :            : 
    1379                 :          0 : static int patch_conexant_build_spdif(struct snd_ac97 * ac97)
    1380                 :            : {
    1381                 :            :         int err;
    1382                 :            : 
    1383                 :            :         /* con mask, pro mask, default */
    1384         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
    1385                 :            :                 return err;
    1386                 :            :         /* switch */
    1387         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0)
    1388                 :            :                 return err;
    1389                 :            :         /* set default PCM S/PDIF params */
    1390                 :            :         /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
    1391                 :          0 :         snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
    1392                 :          0 :                              snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
    1393                 :          0 :         return 0;
    1394                 :            : }
    1395                 :            : 
    1396                 :            : static const struct snd_ac97_build_ops patch_conexant_ops = {
    1397                 :            :         .build_spdif = patch_conexant_build_spdif
    1398                 :            : };
    1399                 :            : 
    1400                 :          0 : static int patch_conexant(struct snd_ac97 * ac97)
    1401                 :            : {
    1402                 :          0 :         ac97->build_ops = &patch_conexant_ops;
    1403                 :          0 :         ac97->flags |= AC97_CX_SPDIF;
    1404                 :          0 :         ac97->ext_id |= AC97_EI_SPDIF;       /* force the detection of spdif */
    1405                 :          0 :         ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
    1406                 :          0 :         return 0;
    1407                 :            : }
    1408                 :            : 
    1409                 :          0 : static int patch_cx20551(struct snd_ac97 *ac97)
    1410                 :            : {
    1411                 :          0 :         snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01);
    1412                 :          0 :         return 0;
    1413                 :            : }
    1414                 :            : 
    1415                 :            : /*
    1416                 :            :  * Analog Device AD18xx, AD19xx codecs
    1417                 :            :  */
    1418                 :            : #ifdef CONFIG_PM
    1419                 :          0 : static void ad18xx_resume(struct snd_ac97 *ac97)
    1420                 :            : {
    1421                 :            :         static unsigned short setup_regs[] = {
    1422                 :            :                 AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF,
    1423                 :            :         };
    1424                 :            :         int i, codec;
    1425                 :            : 
    1426         [ #  # ]:          0 :         for (i = 0; i < (int)ARRAY_SIZE(setup_regs); i++) {
    1427                 :          0 :                 unsigned short reg = setup_regs[i];
    1428         [ #  # ]:          0 :                 if (test_bit(reg, ac97->reg_accessed)) {
    1429                 :          0 :                         snd_ac97_write(ac97, reg, ac97->regs[reg]);
    1430                 :          0 :                         snd_ac97_read(ac97, reg);
    1431                 :            :                 }
    1432                 :            :         }
    1433                 :            : 
    1434         [ #  # ]:          0 :         if (! (ac97->flags & AC97_AD_MULTI))
    1435                 :            :                 /* normal restore */
    1436                 :          0 :                 snd_ac97_restore_status(ac97);
    1437                 :            :         else {
    1438                 :            :                 /* restore the AD18xx codec configurations */
    1439         [ #  # ]:          0 :                 for (codec = 0; codec < 3; codec++) {
    1440         [ #  # ]:          0 :                         if (! ac97->spec.ad18xx.id[codec])
    1441                 :          0 :                                 continue;
    1442                 :            :                         /* select single codec */
    1443                 :          0 :                         snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
    1444                 :          0 :                                              ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
    1445                 :          0 :                         ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
    1446                 :            :                 }
    1447                 :            :                 /* select all codecs */
    1448                 :          0 :                 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
    1449                 :            : 
    1450                 :            :                 /* restore status */
    1451         [ #  # ]:          0 :                 for (i = 2; i < 0x7c ; i += 2) {
    1452         [ #  # ]:          0 :                         if (i == AC97_POWERDOWN || i == AC97_EXTENDED_ID)
    1453                 :          0 :                                 continue;
    1454         [ #  # ]:          0 :                         if (test_bit(i, ac97->reg_accessed)) {
    1455                 :            :                                 /* handle multi codecs for AD18xx */
    1456         [ #  # ]:          0 :                                 if (i == AC97_PCM) {
    1457         [ #  # ]:          0 :                                         for (codec = 0; codec < 3; codec++) {
    1458         [ #  # ]:          0 :                                                 if (! ac97->spec.ad18xx.id[codec])
    1459                 :          0 :                                                         continue;
    1460                 :            :                                                 /* select single codec */
    1461                 :          0 :                                                 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
    1462                 :          0 :                                                                      ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
    1463                 :            :                                                 /* update PCM bits */
    1464                 :          0 :                                                 ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
    1465                 :            :                                         }
    1466                 :            :                                         /* select all codecs */
    1467                 :          0 :                                         snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
    1468                 :          0 :                                         continue;
    1469         [ #  # ]:          0 :                                 } else if (i == AC97_AD_TEST ||
    1470         [ #  # ]:          0 :                                            i == AC97_AD_CODEC_CFG ||
    1471                 :            :                                            i == AC97_AD_SERIAL_CFG)
    1472                 :          0 :                                         continue; /* ignore */
    1473                 :            :                         }
    1474                 :          0 :                         snd_ac97_write(ac97, i, ac97->regs[i]);
    1475                 :          0 :                         snd_ac97_read(ac97, i);
    1476                 :            :                 }
    1477                 :            :         }
    1478                 :            : 
    1479                 :          0 :         snd_ac97_restore_iec958(ac97);
    1480                 :          0 : }
    1481                 :            : 
    1482                 :          0 : static void ad1888_resume(struct snd_ac97 *ac97)
    1483                 :            : {
    1484                 :          0 :         ad18xx_resume(ac97);
    1485                 :          0 :         snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080);
    1486                 :          0 : }
    1487                 :            : 
    1488                 :            : #endif
    1489                 :            : 
    1490                 :            : static const struct snd_ac97_res_table ad1819_restbl[] = {
    1491                 :            :         { AC97_PHONE, 0x9f1f },
    1492                 :            :         { AC97_MIC, 0x9f1f },
    1493                 :            :         { AC97_LINE, 0x9f1f },
    1494                 :            :         { AC97_CD, 0x9f1f },
    1495                 :            :         { AC97_VIDEO, 0x9f1f },
    1496                 :            :         { AC97_AUX, 0x9f1f },
    1497                 :            :         { AC97_PCM, 0x9f1f },
    1498                 :            :         { } /* terminator */
    1499                 :            : };
    1500                 :            : 
    1501                 :          0 : static int patch_ad1819(struct snd_ac97 * ac97)
    1502                 :            : {
    1503                 :            :         unsigned short scfg;
    1504                 :            : 
    1505                 :            :         // patch for Analog Devices
    1506                 :          0 :         scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
    1507                 :          0 :         snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */
    1508                 :          0 :         ac97->res_table = ad1819_restbl;
    1509                 :          0 :         return 0;
    1510                 :            : }
    1511                 :            : 
    1512                 :          0 : static unsigned short patch_ad1881_unchained(struct snd_ac97 * ac97, int idx, unsigned short mask)
    1513                 :            : {
    1514                 :            :         unsigned short val;
    1515                 :            : 
    1516                 :            :         // test for unchained codec
    1517                 :          0 :         snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, mask);
    1518                 :          0 :         snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000);  /* ID0C, ID1C, SDIE = off */
    1519                 :          0 :         val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
    1520         [ #  # ]:          0 :         if ((val & 0xff40) != 0x5340)
    1521                 :            :                 return 0;
    1522                 :          0 :         ac97->spec.ad18xx.unchained[idx] = mask;
    1523                 :          0 :         ac97->spec.ad18xx.id[idx] = val;
    1524                 :          0 :         ac97->spec.ad18xx.codec_cfg[idx] = 0x0000;
    1525                 :          0 :         return mask;
    1526                 :            : }
    1527                 :            : 
    1528                 :          0 : static int patch_ad1881_chained1(struct snd_ac97 * ac97, int idx, unsigned short codec_bits)
    1529                 :            : {
    1530                 :            :         static int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
    1531                 :            :         unsigned short val;
    1532                 :            :         
    1533                 :          0 :         snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, cfg_bits[idx]);
    1534                 :          0 :         snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004);  // SDIE
    1535                 :          0 :         val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
    1536         [ #  # ]:          0 :         if ((val & 0xff40) != 0x5340)
    1537                 :            :                 return 0;
    1538         [ #  # ]:          0 :         if (codec_bits)
    1539                 :          0 :                 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, codec_bits);
    1540                 :          0 :         ac97->spec.ad18xx.chained[idx] = cfg_bits[idx];
    1541                 :          0 :         ac97->spec.ad18xx.id[idx] = val;
    1542         [ #  # ]:          0 :         ac97->spec.ad18xx.codec_cfg[idx] = codec_bits ? codec_bits : 0x0004;
    1543                 :          0 :         return 1;
    1544                 :            : }
    1545                 :            : 
    1546                 :          0 : static void patch_ad1881_chained(struct snd_ac97 * ac97, int unchained_idx, int cidx1, int cidx2)
    1547                 :            : {
    1548                 :            :         // already detected?
    1549 [ #  # ][ #  # ]:          0 :         if (ac97->spec.ad18xx.unchained[cidx1] || ac97->spec.ad18xx.chained[cidx1])
    1550                 :            :                 cidx1 = -1;
    1551 [ #  # ][ #  # ]:          0 :         if (ac97->spec.ad18xx.unchained[cidx2] || ac97->spec.ad18xx.chained[cidx2])
    1552                 :            :                 cidx2 = -1;
    1553         [ #  # ]:          0 :         if (cidx1 < 0 && cidx2 < 0)
    1554                 :          0 :                 return;
    1555                 :            :         // test for chained codecs
    1556                 :          0 :         snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
    1557                 :            :                              ac97->spec.ad18xx.unchained[unchained_idx]);
    1558                 :          0 :         snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002);          // ID1C
    1559                 :          0 :         ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002;
    1560         [ #  # ]:          0 :         if (cidx1 >= 0) {
    1561         [ #  # ]:          0 :                 if (cidx2 < 0)
    1562                 :          0 :                         patch_ad1881_chained1(ac97, cidx1, 0);
    1563         [ #  # ]:          0 :                 else if (patch_ad1881_chained1(ac97, cidx1, 0x0006))    // SDIE | ID1C
    1564                 :          0 :                         patch_ad1881_chained1(ac97, cidx2, 0);
    1565         [ #  # ]:          0 :                 else if (patch_ad1881_chained1(ac97, cidx2, 0x0006))    // SDIE | ID1C
    1566                 :          0 :                         patch_ad1881_chained1(ac97, cidx1, 0);
    1567         [ #  # ]:          0 :         } else if (cidx2 >= 0) {
    1568                 :          0 :                 patch_ad1881_chained1(ac97, cidx2, 0);
    1569                 :            :         }
    1570                 :            : }
    1571                 :            : 
    1572                 :            : static const struct snd_ac97_build_ops patch_ad1881_build_ops = {
    1573                 :            : #ifdef CONFIG_PM
    1574                 :            :         .resume = ad18xx_resume
    1575                 :            : #endif
    1576                 :            : };
    1577                 :            : 
    1578                 :          0 : static int patch_ad1881(struct snd_ac97 * ac97)
    1579                 :            : {
    1580                 :            :         static const char cfg_idxs[3][2] = {
    1581                 :            :                 {2, 1},
    1582                 :            :                 {0, 2},
    1583                 :            :                 {0, 1}
    1584                 :            :         };
    1585                 :            :         
    1586                 :            :         // patch for Analog Devices
    1587                 :            :         unsigned short codecs[3];
    1588                 :            :         unsigned short val;
    1589                 :            :         int idx, num;
    1590                 :            : 
    1591                 :          0 :         val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
    1592                 :          0 :         snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
    1593                 :          0 :         codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
    1594                 :          0 :         codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14));
    1595                 :          0 :         codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13));
    1596                 :            : 
    1597 [ #  # ][ #  # ]:          0 :         if (! (codecs[0] || codecs[1] || codecs[2]))
                 [ #  # ]
    1598                 :            :                 goto __end;
    1599                 :            : 
    1600         [ #  # ]:          0 :         for (idx = 0; idx < 3; idx++)
    1601         [ #  # ]:          0 :                 if (ac97->spec.ad18xx.unchained[idx])
    1602                 :          0 :                         patch_ad1881_chained(ac97, idx, cfg_idxs[idx][0], cfg_idxs[idx][1]);
    1603                 :            : 
    1604         [ #  # ]:          0 :         if (ac97->spec.ad18xx.id[1]) {
    1605                 :          0 :                 ac97->flags |= AC97_AD_MULTI;
    1606                 :          0 :                 ac97->scaps |= AC97_SCAP_SURROUND_DAC;
    1607                 :            :         }
    1608         [ #  # ]:          0 :         if (ac97->spec.ad18xx.id[2]) {
    1609                 :          0 :                 ac97->flags |= AC97_AD_MULTI;
    1610                 :          0 :                 ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
    1611                 :            :         }
    1612                 :            : 
    1613                 :            :       __end:
    1614                 :            :         /* select all codecs */
    1615                 :          0 :         snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
    1616                 :            :         /* check if only one codec is present */
    1617         [ #  # ]:          0 :         for (idx = num = 0; idx < 3; idx++)
    1618         [ #  # ]:          0 :                 if (ac97->spec.ad18xx.id[idx])
    1619                 :          0 :                         num++;
    1620         [ #  # ]:          0 :         if (num == 1) {
    1621                 :            :                 /* ok, deselect all ID bits */
    1622                 :          0 :                 snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000);
    1623                 :          0 :                 ac97->spec.ad18xx.codec_cfg[0] = 
    1624                 :          0 :                         ac97->spec.ad18xx.codec_cfg[1] = 
    1625                 :          0 :                         ac97->spec.ad18xx.codec_cfg[2] = 0x0000;
    1626                 :            :         }
    1627                 :            :         /* required for AD1886/AD1885 combination */
    1628                 :          0 :         ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID);
    1629         [ #  # ]:          0 :         if (ac97->spec.ad18xx.id[0]) {
    1630                 :          0 :                 ac97->id &= 0xffff0000;
    1631                 :          0 :                 ac97->id |= ac97->spec.ad18xx.id[0];
    1632                 :            :         }
    1633                 :          0 :         ac97->build_ops = &patch_ad1881_build_ops;
    1634                 :          0 :         return 0;
    1635                 :            : }
    1636                 :            : 
    1637                 :            : static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = {
    1638                 :            :         AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
    1639                 :            :         /* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */
    1640                 :            :         AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
    1641                 :            :         AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
    1642                 :            :         AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 9, 1, 1), /* inverted */
    1643                 :            :         AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
    1644                 :            : };
    1645                 :            : 
    1646                 :            : static const DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
    1647                 :            : 
    1648                 :          0 : static int patch_ad1885_specific(struct snd_ac97 * ac97)
    1649                 :            : {
    1650                 :            :         int err;
    1651                 :            : 
    1652         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0)
    1653                 :            :                 return err;
    1654                 :          0 :         reset_tlv(ac97, "Headphone Playback Volume",
    1655                 :            :                   db_scale_6bit_6db_max);
    1656                 :          0 :         return 0;
    1657                 :            : }
    1658                 :            : 
    1659                 :            : static const struct snd_ac97_build_ops patch_ad1885_build_ops = {
    1660                 :            :         .build_specific = &patch_ad1885_specific,
    1661                 :            : #ifdef CONFIG_PM
    1662                 :            :         .resume = ad18xx_resume
    1663                 :            : #endif
    1664                 :            : };
    1665                 :            : 
    1666                 :          0 : static int patch_ad1885(struct snd_ac97 * ac97)
    1667                 :            : {
    1668                 :          0 :         patch_ad1881(ac97);
    1669                 :            :         /* This is required to deal with the Intel D815EEAL2 */
    1670                 :            :         /* i.e. Line out is actually headphone out from codec */
    1671                 :            : 
    1672                 :            :         /* set default */
    1673                 :          0 :         snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404);
    1674                 :            : 
    1675                 :          0 :         ac97->build_ops = &patch_ad1885_build_ops;
    1676                 :          0 :         return 0;
    1677                 :            : }
    1678                 :            : 
    1679                 :          0 : static int patch_ad1886_specific(struct snd_ac97 * ac97)
    1680                 :            : {
    1681                 :          0 :         reset_tlv(ac97, "Headphone Playback Volume",
    1682                 :            :                   db_scale_6bit_6db_max);
    1683                 :          0 :         return 0;
    1684                 :            : }
    1685                 :            : 
    1686                 :            : static const struct snd_ac97_build_ops patch_ad1886_build_ops = {
    1687                 :            :         .build_specific = &patch_ad1886_specific,
    1688                 :            : #ifdef CONFIG_PM
    1689                 :            :         .resume = ad18xx_resume
    1690                 :            : #endif
    1691                 :            : };
    1692                 :            : 
    1693                 :          0 : static int patch_ad1886(struct snd_ac97 * ac97)
    1694                 :            : {
    1695                 :          0 :         patch_ad1881(ac97);
    1696                 :            :         /* Presario700 workaround */
    1697                 :            :         /* for Jack Sense/SPDIF Register misetting causing */
    1698                 :          0 :         snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010);
    1699                 :          0 :         ac97->build_ops = &patch_ad1886_build_ops;
    1700                 :          0 :         return 0;
    1701                 :            : }
    1702                 :            : 
    1703                 :            : /* MISC bits (AD1888/AD1980/AD1985 register 0x76) */
    1704                 :            : #define AC97_AD198X_MBC         0x0003  /* mic boost */
    1705                 :            : #define AC97_AD198X_MBC_20      0x0000  /* +20dB */
    1706                 :            : #define AC97_AD198X_MBC_10      0x0001  /* +10dB */
    1707                 :            : #define AC97_AD198X_MBC_30      0x0002  /* +30dB */
    1708                 :            : #define AC97_AD198X_VREFD       0x0004  /* VREF high-Z */
    1709                 :            : #define AC97_AD198X_VREFH       0x0008  /* 0=2.25V, 1=3.7V */
    1710                 :            : #define AC97_AD198X_VREF_0      0x000c  /* 0V (AD1985 only) */
    1711                 :            : #define AC97_AD198X_VREF_MASK   (AC97_AD198X_VREFH | AC97_AD198X_VREFD)
    1712                 :            : #define AC97_AD198X_VREF_SHIFT  2
    1713                 :            : #define AC97_AD198X_SRU         0x0010  /* sample rate unlock */
    1714                 :            : #define AC97_AD198X_LOSEL       0x0020  /* LINE_OUT amplifiers input select */
    1715                 :            : #define AC97_AD198X_2MIC        0x0040  /* 2-channel mic select */
    1716                 :            : #define AC97_AD198X_SPRD        0x0080  /* SPREAD enable */
    1717                 :            : #define AC97_AD198X_DMIX0       0x0100  /* downmix mode: */
    1718                 :            :                                         /*  0 = 6-to-4, 1 = 6-to-2 downmix */
    1719                 :            : #define AC97_AD198X_DMIX1       0x0200  /* downmix mode: 1 = enabled */
    1720                 :            : #define AC97_AD198X_HPSEL       0x0400  /* headphone amplifier input select */
    1721                 :            : #define AC97_AD198X_CLDIS       0x0800  /* center/lfe disable */
    1722                 :            : #define AC97_AD198X_LODIS       0x1000  /* LINE_OUT disable */
    1723                 :            : #define AC97_AD198X_MSPLT       0x2000  /* mute split */
    1724                 :            : #define AC97_AD198X_AC97NC      0x4000  /* AC97 no compatible mode */
    1725                 :            : #define AC97_AD198X_DACZ        0x8000  /* DAC zero-fill mode */
    1726                 :            : 
    1727                 :            : /* MISC 1 bits (AD1986 register 0x76) */
    1728                 :            : #define AC97_AD1986_MBC         0x0003  /* mic boost */
    1729                 :            : #define AC97_AD1986_MBC_20      0x0000  /* +20dB */
    1730                 :            : #define AC97_AD1986_MBC_10      0x0001  /* +10dB */
    1731                 :            : #define AC97_AD1986_MBC_30      0x0002  /* +30dB */
    1732                 :            : #define AC97_AD1986_LISEL0      0x0004  /* LINE_IN select bit 0 */
    1733                 :            : #define AC97_AD1986_LISEL1      0x0008  /* LINE_IN select bit 1 */
    1734                 :            : #define AC97_AD1986_LISEL_MASK  (AC97_AD1986_LISEL1 | AC97_AD1986_LISEL0)
    1735                 :            : #define AC97_AD1986_LISEL_LI    0x0000  /* LINE_IN pins as LINE_IN source */
    1736                 :            : #define AC97_AD1986_LISEL_SURR  0x0004  /* SURROUND pins as LINE_IN source */
    1737                 :            : #define AC97_AD1986_LISEL_MIC   0x0008  /* MIC_1/2 pins as LINE_IN source */
    1738                 :            : #define AC97_AD1986_SRU         0x0010  /* sample rate unlock */
    1739                 :            : #define AC97_AD1986_SOSEL       0x0020  /* SURROUND_OUT amplifiers input sel */
    1740                 :            : #define AC97_AD1986_2MIC        0x0040  /* 2-channel mic select */
    1741                 :            : #define AC97_AD1986_SPRD        0x0080  /* SPREAD enable */
    1742                 :            : #define AC97_AD1986_DMIX0       0x0100  /* downmix mode: */
    1743                 :            :                                         /*  0 = 6-to-4, 1 = 6-to-2 downmix */
    1744                 :            : #define AC97_AD1986_DMIX1       0x0200  /* downmix mode: 1 = enabled */
    1745                 :            : #define AC97_AD1986_CLDIS       0x0800  /* center/lfe disable */
    1746                 :            : #define AC97_AD1986_SODIS       0x1000  /* SURROUND_OUT disable */
    1747                 :            : #define AC97_AD1986_MSPLT       0x2000  /* mute split (read only 1) */
    1748                 :            : #define AC97_AD1986_AC97NC      0x4000  /* AC97 no compatible mode (r/o 1) */
    1749                 :            : #define AC97_AD1986_DACZ        0x8000  /* DAC zero-fill mode */
    1750                 :            : 
    1751                 :            : /* MISC 2 bits (AD1986 register 0x70) */
    1752                 :            : #define AC97_AD_MISC2           0x70    /* Misc Control Bits 2 (AD1986) */
    1753                 :            : 
    1754                 :            : #define AC97_AD1986_CVREF0      0x0004  /* C/LFE VREF_OUT 2.25V */
    1755                 :            : #define AC97_AD1986_CVREF1      0x0008  /* C/LFE VREF_OUT 0V */
    1756                 :            : #define AC97_AD1986_CVREF2      0x0010  /* C/LFE VREF_OUT 3.7V */
    1757                 :            : #define AC97_AD1986_CVREF_MASK \
    1758                 :            :         (AC97_AD1986_CVREF2 | AC97_AD1986_CVREF1 | AC97_AD1986_CVREF0)
    1759                 :            : #define AC97_AD1986_JSMAP       0x0020  /* Jack Sense Mapping 1 = alternate */
    1760                 :            : #define AC97_AD1986_MMDIS       0x0080  /* Mono Mute Disable */
    1761                 :            : #define AC97_AD1986_MVREF0      0x0400  /* MIC VREF_OUT 2.25V */
    1762                 :            : #define AC97_AD1986_MVREF1      0x0800  /* MIC VREF_OUT 0V */
    1763                 :            : #define AC97_AD1986_MVREF2      0x1000  /* MIC VREF_OUT 3.7V */
    1764                 :            : #define AC97_AD1986_MVREF_MASK \
    1765                 :            :         (AC97_AD1986_MVREF2 | AC97_AD1986_MVREF1 | AC97_AD1986_MVREF0)
    1766                 :            : 
    1767                 :            : /* MISC 3 bits (AD1986 register 0x7a) */
    1768                 :            : #define AC97_AD_MISC3           0x7a    /* Misc Control Bits 3 (AD1986) */
    1769                 :            : 
    1770                 :            : #define AC97_AD1986_MMIX        0x0004  /* Mic Mix, left/right */
    1771                 :            : #define AC97_AD1986_GPO         0x0008  /* General Purpose Out */
    1772                 :            : #define AC97_AD1986_LOHPEN      0x0010  /* LINE_OUT headphone drive */
    1773                 :            : #define AC97_AD1986_LVREF0      0x0100  /* LINE_OUT VREF_OUT 2.25V */
    1774                 :            : #define AC97_AD1986_LVREF1      0x0200  /* LINE_OUT VREF_OUT 0V */
    1775                 :            : #define AC97_AD1986_LVREF2      0x0400  /* LINE_OUT VREF_OUT 3.7V */
    1776                 :            : #define AC97_AD1986_LVREF_MASK \
    1777                 :            :         (AC97_AD1986_LVREF2 | AC97_AD1986_LVREF1 | AC97_AD1986_LVREF0)
    1778                 :            : #define AC97_AD1986_JSINVA      0x0800  /* Jack Sense Invert SENSE_A */
    1779                 :            : #define AC97_AD1986_LOSEL       0x1000  /* LINE_OUT amplifiers input select */
    1780                 :            : #define AC97_AD1986_HPSEL0      0x2000  /* Headphone amplifiers */
    1781                 :            :                                         /*   input select Surround DACs */
    1782                 :            : #define AC97_AD1986_HPSEL1      0x4000  /* Headphone amplifiers input */
    1783                 :            :                                         /*   select C/LFE DACs */
    1784                 :            : #define AC97_AD1986_JSINVB      0x8000  /* Jack Sense Invert SENSE_B */
    1785                 :            : 
    1786                 :            : /* Serial Config bits (AD1986 register 0x74) (incomplete) */
    1787                 :            : #define AC97_AD1986_OMS0        0x0100  /* Optional Mic Selector bit 0 */
    1788                 :            : #define AC97_AD1986_OMS1        0x0200  /* Optional Mic Selector bit 1 */
    1789                 :            : #define AC97_AD1986_OMS2        0x0400  /* Optional Mic Selector bit 2 */
    1790                 :            : #define AC97_AD1986_OMS_MASK \
    1791                 :            :         (AC97_AD1986_OMS2 | AC97_AD1986_OMS1 | AC97_AD1986_OMS0)
    1792                 :            : #define AC97_AD1986_OMS_M       0x0000  /* MIC_1/2 pins are MIC sources */
    1793                 :            : #define AC97_AD1986_OMS_L       0x0100  /* LINE_IN pins are MIC sources */
    1794                 :            : #define AC97_AD1986_OMS_C       0x0200  /* Center/LFE pins are MCI sources */
    1795                 :            : #define AC97_AD1986_OMS_MC      0x0400  /* Mix of MIC and C/LFE pins */
    1796                 :            :                                         /*   are MIC sources */
    1797                 :            : #define AC97_AD1986_OMS_ML      0x0500  /* MIX of MIC and LINE_IN pins */
    1798                 :            :                                         /*   are MIC sources */
    1799                 :            : #define AC97_AD1986_OMS_LC      0x0600  /* MIX of LINE_IN and C/LFE pins */
    1800                 :            :                                         /*   are MIC sources */
    1801                 :            : #define AC97_AD1986_OMS_MLC     0x0700  /* MIX of MIC, LINE_IN, C/LFE pins */
    1802                 :            :                                         /*   are MIC sources */
    1803                 :            : 
    1804                 :            : 
    1805                 :          0 : static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    1806                 :            : {
    1807                 :            :         static char *texts[2] = { "AC-Link", "A/D Converter" };
    1808                 :            : 
    1809                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
    1810                 :          0 :         uinfo->count = 1;
    1811                 :          0 :         uinfo->value.enumerated.items = 2;
    1812         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 1)
    1813                 :          0 :                 uinfo->value.enumerated.item = 1;
    1814                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
    1815                 :          0 :         return 0;
    1816                 :            : }
    1817                 :            : 
    1818                 :          0 : static int snd_ac97_ad198x_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1819                 :            : {
    1820                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1821                 :            :         unsigned short val;
    1822                 :            : 
    1823                 :          0 :         val = ac97->regs[AC97_AD_SERIAL_CFG];
    1824                 :          0 :         ucontrol->value.enumerated.item[0] = (val >> 2) & 1;
    1825                 :          0 :         return 0;
    1826                 :            : }
    1827                 :            : 
    1828                 :          0 : static int snd_ac97_ad198x_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1829                 :            : {
    1830                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1831                 :            :         unsigned short val;
    1832                 :            : 
    1833         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] > 1)
    1834                 :            :                 return -EINVAL;
    1835                 :          0 :         val = ucontrol->value.enumerated.item[0] << 2;
    1836                 :          0 :         return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
    1837                 :            : }
    1838                 :            : 
    1839                 :            : static const struct snd_kcontrol_new snd_ac97_ad198x_spdif_source = {
    1840                 :            :         .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
    1841                 :            :         .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
    1842                 :            :         .info   = snd_ac97_ad198x_spdif_source_info,
    1843                 :            :         .get    = snd_ac97_ad198x_spdif_source_get,
    1844                 :            :         .put    = snd_ac97_ad198x_spdif_source_put,
    1845                 :            : };
    1846                 :            : 
    1847                 :          0 : static int patch_ad198x_post_spdif(struct snd_ac97 * ac97)
    1848                 :            : {
    1849                 :          0 :         return patch_build_controls(ac97, &snd_ac97_ad198x_spdif_source, 1);
    1850                 :            : }
    1851                 :            : 
    1852                 :            : static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = {
    1853                 :            :         AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 11, 1, 0),
    1854                 :            :         AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
    1855                 :            : };
    1856                 :            : 
    1857                 :            : /* black list to avoid HP/Line jack-sense controls
    1858                 :            :  * (SS vendor << 16 | device)
    1859                 :            :  */
    1860                 :            : static unsigned int ad1981_jacks_blacklist[] = {
    1861                 :            :         0x10140523, /* Thinkpad R40 */
    1862                 :            :         0x10140534, /* Thinkpad X31 */
    1863                 :            :         0x10140537, /* Thinkpad T41p */
    1864                 :            :         0x1014053e, /* Thinkpad R40e */
    1865                 :            :         0x10140554, /* Thinkpad T42p/R50p */
    1866                 :            :         0x10140567, /* Thinkpad T43p 2668-G7U */
    1867                 :            :         0x10140581, /* Thinkpad X41-2527 */
    1868                 :            :         0x10280160, /* Dell Dimension 2400 */
    1869                 :            :         0x104380b0, /* Asus A7V8X-MX */
    1870                 :            :         0x11790241, /* Toshiba Satellite A-15 S127 */
    1871                 :            :         0x1179ff10, /* Toshiba P500 */
    1872                 :            :         0x144dc01a, /* Samsung NP-X20C004/SEG */
    1873                 :            :         0 /* end */
    1874                 :            : };
    1875                 :            : 
    1876                 :            : static int check_list(struct snd_ac97 *ac97, const unsigned int *list)
    1877                 :            : {
    1878                 :          0 :         u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
    1879 [ #  # ][ #  # ]:          0 :         for (; *list; list++)
                 [ #  # ]
    1880 [ #  # ][ #  # ]:          0 :                 if (*list == subid)
                 [ #  # ]
    1881                 :            :                         return 1;
    1882                 :            :         return 0;
    1883                 :            : }
    1884                 :            : 
    1885                 :          0 : static int patch_ad1981a_specific(struct snd_ac97 * ac97)
    1886                 :            : {
    1887         [ #  # ]:          0 :         if (check_list(ac97, ad1981_jacks_blacklist))
    1888                 :            :                 return 0;
    1889                 :          0 :         return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
    1890                 :            :                                     ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
    1891                 :            : }
    1892                 :            : 
    1893                 :            : static const struct snd_ac97_build_ops patch_ad1981a_build_ops = {
    1894                 :            :         .build_post_spdif = patch_ad198x_post_spdif,
    1895                 :            :         .build_specific = patch_ad1981a_specific,
    1896                 :            : #ifdef CONFIG_PM
    1897                 :            :         .resume = ad18xx_resume
    1898                 :            : #endif
    1899                 :            : };
    1900                 :            : 
    1901                 :            : /* white list to enable HP jack-sense bits
    1902                 :            :  * (SS vendor << 16 | device)
    1903                 :            :  */
    1904                 :            : static unsigned int ad1981_jacks_whitelist[] = {
    1905                 :            :         0x0e11005a, /* HP nc4000/4010 */
    1906                 :            :         0x103c0890, /* HP nc6000 */
    1907                 :            :         0x103c0938, /* HP nc4220 */
    1908                 :            :         0x103c099c, /* HP nx6110 */
    1909                 :            :         0x103c0944, /* HP nc6220 */
    1910                 :            :         0x103c0934, /* HP nc8220 */
    1911                 :            :         0x103c006d, /* HP nx9105 */
    1912                 :            :         0x103c300d, /* HP Compaq dc5100 SFF(PT003AW) */
    1913                 :            :         0x17340088, /* FSC Scenic-W */
    1914                 :            :         0 /* end */
    1915                 :            : };
    1916                 :            : 
    1917                 :          0 : static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97)
    1918                 :            : {
    1919         [ #  # ]:          0 :         if (check_list(ac97, ad1981_jacks_whitelist))
    1920                 :            :                 /* enable headphone jack sense */
    1921                 :          0 :                 snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11);
    1922                 :          0 : }
    1923                 :            : 
    1924                 :          0 : static int patch_ad1981a(struct snd_ac97 *ac97)
    1925                 :            : {
    1926                 :          0 :         patch_ad1881(ac97);
    1927                 :          0 :         ac97->build_ops = &patch_ad1981a_build_ops;
    1928                 :          0 :         snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
    1929                 :          0 :         ac97->flags |= AC97_STEREO_MUTES;
    1930                 :          0 :         check_ad1981_hp_jack_sense(ac97);
    1931                 :          0 :         return 0;
    1932                 :            : }
    1933                 :            : 
    1934                 :            : static const struct snd_kcontrol_new snd_ac97_ad198x_2cmic =
    1935                 :            : AC97_SINGLE("Stereo Mic", AC97_AD_MISC, 6, 1, 0);
    1936                 :            : 
    1937                 :          0 : static int patch_ad1981b_specific(struct snd_ac97 *ac97)
    1938                 :            : {
    1939                 :            :         int err;
    1940                 :            : 
    1941         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
    1942                 :            :                 return err;
    1943         [ #  # ]:          0 :         if (check_list(ac97, ad1981_jacks_blacklist))
    1944                 :            :                 return 0;
    1945                 :          0 :         return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
    1946                 :            :                                     ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
    1947                 :            : }
    1948                 :            : 
    1949                 :            : static const struct snd_ac97_build_ops patch_ad1981b_build_ops = {
    1950                 :            :         .build_post_spdif = patch_ad198x_post_spdif,
    1951                 :            :         .build_specific = patch_ad1981b_specific,
    1952                 :            : #ifdef CONFIG_PM
    1953                 :            :         .resume = ad18xx_resume
    1954                 :            : #endif
    1955                 :            : };
    1956                 :            : 
    1957                 :          0 : static int patch_ad1981b(struct snd_ac97 *ac97)
    1958                 :            : {
    1959                 :          0 :         patch_ad1881(ac97);
    1960                 :          0 :         ac97->build_ops = &patch_ad1981b_build_ops;
    1961                 :          0 :         snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD198X_MSPLT, AC97_AD198X_MSPLT);
    1962                 :          0 :         ac97->flags |= AC97_STEREO_MUTES;
    1963                 :          0 :         check_ad1981_hp_jack_sense(ac97);
    1964                 :          0 :         return 0;
    1965                 :            : }
    1966                 :            : 
    1967                 :            : #define snd_ac97_ad1888_lohpsel_info    snd_ctl_boolean_mono_info
    1968                 :            : 
    1969                 :          0 : static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1970                 :            : {
    1971                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1972                 :            :         unsigned short val;
    1973                 :            : 
    1974                 :          0 :         val = ac97->regs[AC97_AD_MISC];
    1975                 :          0 :         ucontrol->value.integer.value[0] = !(val & AC97_AD198X_LOSEL);
    1976         [ #  # ]:          0 :         if (ac97->spec.ad18xx.lo_as_master)
    1977                 :          0 :                 ucontrol->value.integer.value[0] =
    1978                 :          0 :                         !ucontrol->value.integer.value[0];
    1979                 :          0 :         return 0;
    1980                 :            : }
    1981                 :            : 
    1982                 :          0 : static int snd_ac97_ad1888_lohpsel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    1983                 :            : {
    1984                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    1985                 :            :         unsigned short val;
    1986                 :            : 
    1987                 :          0 :         val = !ucontrol->value.integer.value[0];
    1988         [ #  # ]:          0 :         if (ac97->spec.ad18xx.lo_as_master)
    1989                 :          0 :                 val = !val;
    1990         [ #  # ]:          0 :         val = val ? (AC97_AD198X_LOSEL | AC97_AD198X_HPSEL) : 0;
    1991                 :          0 :         return snd_ac97_update_bits(ac97, AC97_AD_MISC,
    1992                 :            :                                     AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val);
    1993                 :            : }
    1994                 :            : 
    1995                 :          0 : static int snd_ac97_ad1888_downmix_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    1996                 :            : {
    1997                 :            :         static char *texts[3] = {"Off", "6 -> 4", "6 -> 2"};
    1998                 :            : 
    1999                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
    2000                 :          0 :         uinfo->count = 1;
    2001                 :          0 :         uinfo->value.enumerated.items = 3;
    2002         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 2)
    2003                 :          0 :                 uinfo->value.enumerated.item = 2;
    2004                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
    2005                 :          0 :         return 0;
    2006                 :            : }
    2007                 :            : 
    2008                 :          0 : static int snd_ac97_ad1888_downmix_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    2009                 :            : {
    2010                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2011                 :            :         unsigned short val;
    2012                 :            : 
    2013                 :          0 :         val = ac97->regs[AC97_AD_MISC];
    2014         [ #  # ]:          0 :         if (!(val & AC97_AD198X_DMIX1))
    2015                 :          0 :                 ucontrol->value.enumerated.item[0] = 0;
    2016                 :            :         else
    2017                 :          0 :                 ucontrol->value.enumerated.item[0] = 1 + ((val >> 8) & 1);
    2018                 :          0 :         return 0;
    2019                 :            : }
    2020                 :            : 
    2021                 :          0 : static int snd_ac97_ad1888_downmix_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    2022                 :            : {
    2023                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2024                 :            :         unsigned short val;
    2025                 :            : 
    2026         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] > 2)
    2027                 :            :                 return -EINVAL;
    2028         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] == 0)
    2029                 :            :                 val = 0;
    2030                 :            :         else
    2031                 :          0 :                 val = AC97_AD198X_DMIX1 |
    2032                 :            :                         ((ucontrol->value.enumerated.item[0] - 1) << 8);
    2033                 :          0 :         return snd_ac97_update_bits(ac97, AC97_AD_MISC,
    2034                 :            :                                     AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
    2035                 :            : }
    2036                 :            : 
    2037                 :          0 : static void ad1888_update_jacks(struct snd_ac97 *ac97)
    2038                 :            : {
    2039                 :            :         unsigned short val = 0;
    2040                 :            :         /* clear LODIS if shared jack is to be used for Surround out */
    2041 [ #  # ][ #  # ]:          0 :         if (!ac97->spec.ad18xx.lo_as_master && is_shared_linein(ac97))
    2042                 :            :                 val |= (1 << 12);
    2043                 :            :         /* clear CLDIS if shared jack is to be used for C/LFE out */
    2044         [ #  # ]:          0 :         if (is_shared_micin(ac97))
    2045                 :          0 :                 val |= (1 << 11);
    2046                 :            :         /* shared Line-In */
    2047                 :          0 :         snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val);
    2048                 :          0 : }
    2049                 :            : 
    2050                 :            : static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = {
    2051                 :            :         {
    2052                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2053                 :            :                 .name = "Exchange Front/Surround",
    2054                 :            :                 .info = snd_ac97_ad1888_lohpsel_info,
    2055                 :            :                 .get = snd_ac97_ad1888_lohpsel_get,
    2056                 :            :                 .put = snd_ac97_ad1888_lohpsel_put
    2057                 :            :         },
    2058                 :            :         AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, AC97_AD_VREFD_SHIFT, 1, 1),
    2059                 :            :         AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2,
    2060                 :            :                         AC97_AD_HPFD_SHIFT, 1, 1),
    2061                 :            :         AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0),
    2062                 :            :         {
    2063                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2064                 :            :                 .name = "Downmix",
    2065                 :            :                 .info = snd_ac97_ad1888_downmix_info,
    2066                 :            :                 .get = snd_ac97_ad1888_downmix_get,
    2067                 :            :                 .put = snd_ac97_ad1888_downmix_put
    2068                 :            :         },
    2069                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    2070                 :            :         AC97_CHANNEL_MODE_CTL,
    2071                 :            : 
    2072                 :            :         AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
    2073                 :            :         AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
    2074                 :            : };
    2075                 :            : 
    2076                 :          0 : static int patch_ad1888_specific(struct snd_ac97 *ac97)
    2077                 :            : {
    2078         [ #  # ]:          0 :         if (!ac97->spec.ad18xx.lo_as_master) {
    2079                 :            :                 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
    2080                 :          0 :                 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
    2081                 :            :                                         "Master Surround Playback");
    2082                 :          0 :                 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback",
    2083                 :            :                                         "Master Playback");
    2084                 :            :         }
    2085                 :          0 :         return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
    2086                 :            : }
    2087                 :            : 
    2088                 :            : static const struct snd_ac97_build_ops patch_ad1888_build_ops = {
    2089                 :            :         .build_post_spdif = patch_ad198x_post_spdif,
    2090                 :            :         .build_specific = patch_ad1888_specific,
    2091                 :            : #ifdef CONFIG_PM
    2092                 :            :         .resume = ad1888_resume,
    2093                 :            : #endif
    2094                 :            :         .update_jacks = ad1888_update_jacks,
    2095                 :            : };
    2096                 :            : 
    2097                 :          0 : static int patch_ad1888(struct snd_ac97 * ac97)
    2098                 :            : {
    2099                 :            :         unsigned short misc;
    2100                 :            :         
    2101                 :          0 :         patch_ad1881(ac97);
    2102                 :          0 :         ac97->build_ops = &patch_ad1888_build_ops;
    2103                 :            : 
    2104                 :            :         /*
    2105                 :            :          * LO can be used as a real line-out on some devices,
    2106                 :            :          * and we need to revert the front/surround mixer switches
    2107                 :            :          */
    2108         [ #  # ]:          0 :         if (ac97->subsystem_vendor == 0x1043 &&
    2109                 :            :             ac97->subsystem_device == 0x1193) /* ASUS A9T laptop */
    2110                 :          0 :                 ac97->spec.ad18xx.lo_as_master = 1;
    2111                 :            : 
    2112                 :          0 :         misc = snd_ac97_read(ac97, AC97_AD_MISC);
    2113                 :            :         /* AD-compatible mode */
    2114                 :            :         /* Stereo mutes enabled */
    2115                 :          0 :         misc |= AC97_AD198X_MSPLT | AC97_AD198X_AC97NC;
    2116         [ #  # ]:          0 :         if (!ac97->spec.ad18xx.lo_as_master)
    2117                 :            :                 /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
    2118                 :            :                 /* it seems that most vendors connect line-out connector to
    2119                 :            :                  * headphone out of AC'97
    2120                 :            :                  */
    2121                 :          0 :                 misc |= AC97_AD198X_LOSEL | AC97_AD198X_HPSEL;
    2122                 :            : 
    2123                 :          0 :         snd_ac97_write_cache(ac97, AC97_AD_MISC, misc);
    2124                 :          0 :         ac97->flags |= AC97_STEREO_MUTES;
    2125                 :          0 :         return 0;
    2126                 :            : }
    2127                 :            : 
    2128                 :          0 : static int patch_ad1980_specific(struct snd_ac97 *ac97)
    2129                 :            : {
    2130                 :            :         int err;
    2131                 :            : 
    2132         [ #  # ]:          0 :         if ((err = patch_ad1888_specific(ac97)) < 0)
    2133                 :            :                 return err;
    2134                 :          0 :         return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1);
    2135                 :            : }
    2136                 :            : 
    2137                 :            : static const struct snd_ac97_build_ops patch_ad1980_build_ops = {
    2138                 :            :         .build_post_spdif = patch_ad198x_post_spdif,
    2139                 :            :         .build_specific = patch_ad1980_specific,
    2140                 :            : #ifdef CONFIG_PM
    2141                 :            :         .resume = ad18xx_resume,
    2142                 :            : #endif
    2143                 :            :         .update_jacks = ad1888_update_jacks,
    2144                 :            : };
    2145                 :            : 
    2146                 :          0 : static int patch_ad1980(struct snd_ac97 * ac97)
    2147                 :            : {
    2148                 :          0 :         patch_ad1888(ac97);
    2149                 :          0 :         ac97->build_ops = &patch_ad1980_build_ops;
    2150                 :          0 :         return 0;
    2151                 :            : }
    2152                 :            : 
    2153                 :          0 : static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
    2154                 :            :                                         struct snd_ctl_elem_info *uinfo)
    2155                 :            : {
    2156                 :            :         static char *texts[4] = {"High-Z", "3.7 V", "2.25 V", "0 V"};
    2157                 :            : 
    2158                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
    2159                 :          0 :         uinfo->count = 1;
    2160                 :          0 :         uinfo->value.enumerated.items = 4;
    2161         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 3)
    2162                 :          0 :                 uinfo->value.enumerated.item = 3;
    2163                 :          0 :         strcpy(uinfo->value.enumerated.name,
    2164                 :          0 :                texts[uinfo->value.enumerated.item]);
    2165                 :          0 :         return 0;
    2166                 :            : }
    2167                 :            : 
    2168                 :          0 : static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
    2169                 :            :                                        struct snd_ctl_elem_value *ucontrol)
    2170                 :            : {
    2171                 :            :         static const int reg2ctrl[4] = {2, 0, 1, 3};
    2172                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2173                 :            :         unsigned short val;
    2174                 :          0 :         val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
    2175                 :          0 :               >> AC97_AD198X_VREF_SHIFT;
    2176                 :          0 :         ucontrol->value.enumerated.item[0] = reg2ctrl[val];
    2177                 :          0 :         return 0;
    2178                 :            : }
    2179                 :            : 
    2180                 :          0 : static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol, 
    2181                 :            :                                        struct snd_ctl_elem_value *ucontrol)
    2182                 :            : {
    2183                 :            :         static const int ctrl2reg[4] = {1, 2, 0, 3};
    2184                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2185                 :            :         unsigned short val;
    2186                 :            : 
    2187         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] > 3)
    2188                 :            :                 return -EINVAL;
    2189                 :          0 :         val = ctrl2reg[ucontrol->value.enumerated.item[0]]
    2190                 :            :               << AC97_AD198X_VREF_SHIFT;
    2191                 :          0 :         return snd_ac97_update_bits(ac97, AC97_AD_MISC,
    2192                 :            :                                     AC97_AD198X_VREF_MASK, val);
    2193                 :            : }
    2194                 :            : 
    2195                 :            : static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
    2196                 :            :         AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
    2197                 :            :         {
    2198                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2199                 :            :                 .name = "Exchange Front/Surround",
    2200                 :            :                 .info = snd_ac97_ad1888_lohpsel_info,
    2201                 :            :                 .get = snd_ac97_ad1888_lohpsel_get,
    2202                 :            :                 .put = snd_ac97_ad1888_lohpsel_put
    2203                 :            :         },
    2204                 :            :         AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
    2205                 :            :         AC97_SINGLE("Spread Front to Surround and Center/LFE",
    2206                 :            :                     AC97_AD_MISC, 7, 1, 0),
    2207                 :            :         {
    2208                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2209                 :            :                 .name = "Downmix",
    2210                 :            :                 .info = snd_ac97_ad1888_downmix_info,
    2211                 :            :                 .get = snd_ac97_ad1888_downmix_get,
    2212                 :            :                 .put = snd_ac97_ad1888_downmix_put
    2213                 :            :         },
    2214                 :            :         {
    2215                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2216                 :            :                 .name = "V_REFOUT",
    2217                 :            :                 .info = snd_ac97_ad1985_vrefout_info,
    2218                 :            :                 .get = snd_ac97_ad1985_vrefout_get,
    2219                 :            :                 .put = snd_ac97_ad1985_vrefout_put
    2220                 :            :         },
    2221                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    2222                 :            :         AC97_CHANNEL_MODE_CTL,
    2223                 :            : 
    2224                 :            :         AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
    2225                 :            :         AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
    2226                 :            : };
    2227                 :            : 
    2228                 :          0 : static void ad1985_update_jacks(struct snd_ac97 *ac97)
    2229                 :            : {
    2230                 :          0 :         ad1888_update_jacks(ac97);
    2231                 :            :         /* clear OMS if shared jack is to be used for C/LFE out */
    2232         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
    2233                 :            :                              is_shared_micin(ac97) ? 1 << 9 : 0);
    2234                 :          0 : }
    2235                 :            : 
    2236                 :          0 : static int patch_ad1985_specific(struct snd_ac97 *ac97)
    2237                 :            : {
    2238                 :            :         int err;
    2239                 :            : 
    2240                 :            :         /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
    2241                 :          0 :         snd_ac97_rename_vol_ctl(ac97, "Master Playback",
    2242                 :            :                                 "Master Surround Playback");
    2243                 :          0 :         snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
    2244                 :            : 
    2245         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
    2246                 :            :                 return err;
    2247                 :            : 
    2248                 :          0 :         return patch_build_controls(ac97, snd_ac97_ad1985_controls,
    2249                 :            :                                     ARRAY_SIZE(snd_ac97_ad1985_controls));
    2250                 :            : }
    2251                 :            : 
    2252                 :            : static const struct snd_ac97_build_ops patch_ad1985_build_ops = {
    2253                 :            :         .build_post_spdif = patch_ad198x_post_spdif,
    2254                 :            :         .build_specific = patch_ad1985_specific,
    2255                 :            : #ifdef CONFIG_PM
    2256                 :            :         .resume = ad18xx_resume,
    2257                 :            : #endif
    2258                 :            :         .update_jacks = ad1985_update_jacks,
    2259                 :            : };
    2260                 :            : 
    2261                 :          0 : static int patch_ad1985(struct snd_ac97 * ac97)
    2262                 :            : {
    2263                 :            :         unsigned short misc;
    2264                 :            :         
    2265                 :          0 :         patch_ad1881(ac97);
    2266                 :          0 :         ac97->build_ops = &patch_ad1985_build_ops;
    2267                 :          0 :         misc = snd_ac97_read(ac97, AC97_AD_MISC);
    2268                 :            :         /* switch front/surround line-out/hp-out */
    2269                 :            :         /* AD-compatible mode */
    2270                 :            :         /* Stereo mutes enabled */
    2271                 :          0 :         snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
    2272                 :            :                              AC97_AD198X_LOSEL |
    2273                 :            :                              AC97_AD198X_HPSEL |
    2274                 :            :                              AC97_AD198X_MSPLT |
    2275                 :            :                              AC97_AD198X_AC97NC);
    2276                 :          0 :         ac97->flags |= AC97_STEREO_MUTES;
    2277                 :            : 
    2278                 :            :         /* update current jack configuration */
    2279                 :          0 :         ad1985_update_jacks(ac97);
    2280                 :            : 
    2281                 :            :         /* on AD1985 rev. 3, AC'97 revision bits are zero */
    2282                 :          0 :         ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
    2283                 :          0 :         return 0;
    2284                 :            : }
    2285                 :            : 
    2286                 :            : #define snd_ac97_ad1986_bool_info       snd_ctl_boolean_mono_info
    2287                 :            : 
    2288                 :          0 : static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
    2289                 :            :                                        struct snd_ctl_elem_value *ucontrol)
    2290                 :            : {
    2291                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2292                 :            :         unsigned short val;
    2293                 :            : 
    2294                 :          0 :         val = ac97->regs[AC97_AD_MISC3];
    2295                 :          0 :         ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0;
    2296                 :          0 :         return 0;
    2297                 :            : }
    2298                 :            : 
    2299                 :          0 : static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol,
    2300                 :            :                                        struct snd_ctl_elem_value *ucontrol)
    2301                 :            : {
    2302                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2303                 :            :         int ret0;
    2304                 :            :         int ret1;
    2305                 :          0 :         int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0;
    2306                 :            : 
    2307         [ #  # ]:          0 :         ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL,
    2308                 :          0 :                                         ucontrol->value.integer.value[0] != 0
    2309                 :            :                                     ? AC97_AD1986_LOSEL : 0);
    2310         [ #  # ]:          0 :         if (ret0 < 0)
    2311                 :            :                 return ret0;
    2312                 :            : 
    2313                 :            :         /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
    2314         [ #  # ]:          0 :         ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
    2315                 :          0 :                                     (ucontrol->value.integer.value[0] != 0
    2316         [ #  # ]:          0 :                                      || sprd)
    2317                 :            :                                     ? AC97_AD1986_SOSEL : 0);
    2318         [ #  # ]:          0 :         if (ret1 < 0)
    2319                 :            :                 return ret1;
    2320                 :            : 
    2321                 :          0 :         return (ret0 > 0 || ret1 > 0) ? 1 : 0;
    2322                 :            : }
    2323                 :            : 
    2324                 :          0 : static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol,
    2325                 :            :                                       struct snd_ctl_elem_value *ucontrol)
    2326                 :            : {
    2327                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2328                 :            :         unsigned short val;
    2329                 :            : 
    2330                 :          0 :         val = ac97->regs[AC97_AD_MISC];
    2331                 :          0 :         ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0;
    2332                 :          0 :         return 0;
    2333                 :            : }
    2334                 :            : 
    2335                 :          0 : static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol,
    2336                 :            :                                       struct snd_ctl_elem_value *ucontrol)
    2337                 :            : {
    2338                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2339                 :            :         int ret0;
    2340                 :            :         int ret1;
    2341                 :          0 :         int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0;
    2342                 :            : 
    2343         [ #  # ]:          0 :         ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD,
    2344                 :          0 :                                         ucontrol->value.integer.value[0] != 0
    2345                 :            :                                     ? AC97_AD1986_SPRD : 0);
    2346         [ #  # ]:          0 :         if (ret0 < 0)
    2347                 :            :                 return ret0;
    2348                 :            : 
    2349                 :            :         /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
    2350         [ #  # ]:          0 :         ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
    2351                 :          0 :                                     (ucontrol->value.integer.value[0] != 0
    2352         [ #  # ]:          0 :                                      || sprd)
    2353                 :            :                                     ? AC97_AD1986_SOSEL : 0);
    2354         [ #  # ]:          0 :         if (ret1 < 0)
    2355                 :            :                 return ret1;
    2356                 :            : 
    2357                 :          0 :         return (ret0 > 0 || ret1 > 0) ? 1 : 0;
    2358                 :            : }
    2359                 :            : 
    2360                 :          0 : static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol,
    2361                 :            :                                         struct snd_ctl_elem_value *ucontrol)
    2362                 :            : {
    2363                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2364                 :            : 
    2365                 :          0 :         ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein;
    2366                 :          0 :         return 0;
    2367                 :            : }
    2368                 :            : 
    2369                 :          0 : static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol,
    2370                 :            :                                         struct snd_ctl_elem_value *ucontrol)
    2371                 :            : {
    2372                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2373                 :          0 :         unsigned char swap = ucontrol->value.integer.value[0] != 0;
    2374                 :            : 
    2375         [ #  # ]:          0 :         if (swap != ac97->spec.ad18xx.swap_mic_linein) {
    2376                 :          0 :                 ac97->spec.ad18xx.swap_mic_linein = swap;
    2377         [ #  # ]:          0 :                 if (ac97->build_ops->update_jacks)
    2378                 :          0 :                         ac97->build_ops->update_jacks(ac97);
    2379                 :            :                 return 1;
    2380                 :            :         }
    2381                 :            :         return 0;
    2382                 :            : }
    2383                 :            : 
    2384                 :          0 : static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol,
    2385                 :            :                                        struct snd_ctl_elem_value *ucontrol)
    2386                 :            : {
    2387                 :            :         /* Use MIC_1/2 V_REFOUT as the "get" value */
    2388                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2389                 :            :         unsigned short val;
    2390                 :          0 :         unsigned short reg = ac97->regs[AC97_AD_MISC2];
    2391         [ #  # ]:          0 :         if ((reg & AC97_AD1986_MVREF0) != 0)
    2392                 :            :                 val = 2;
    2393         [ #  # ]:          0 :         else if ((reg & AC97_AD1986_MVREF1) != 0)
    2394                 :            :                 val = 3;
    2395         [ #  # ]:          0 :         else if ((reg & AC97_AD1986_MVREF2) != 0)
    2396                 :            :                 val = 1;
    2397                 :            :         else
    2398                 :            :                 val = 0;
    2399                 :          0 :         ucontrol->value.enumerated.item[0] = val;
    2400                 :          0 :         return 0;
    2401                 :            : }
    2402                 :            : 
    2403                 :          0 : static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol,
    2404                 :            :                                        struct snd_ctl_elem_value *ucontrol)
    2405                 :            : {
    2406                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2407                 :            :         unsigned short cval;
    2408                 :            :         unsigned short lval;
    2409                 :            :         unsigned short mval;
    2410                 :            :         int cret;
    2411                 :            :         int lret;
    2412                 :            :         int mret;
    2413                 :            : 
    2414   [ #  #  #  #  :          0 :         switch (ucontrol->value.enumerated.item[0])
                      # ]
    2415                 :            :         {
    2416                 :            :         case 0: /* High-Z */
    2417                 :            :                 cval = 0;
    2418                 :            :                 lval = 0;
    2419                 :            :                 mval = 0;
    2420                 :            :                 break;
    2421                 :            :         case 1: /* 3.7 V */
    2422                 :            :                 cval = AC97_AD1986_CVREF2;
    2423                 :            :                 lval = AC97_AD1986_LVREF2;
    2424                 :            :                 mval = AC97_AD1986_MVREF2;
    2425                 :          0 :                 break;
    2426                 :            :         case 2: /* 2.25 V */
    2427                 :            :                 cval = AC97_AD1986_CVREF0;
    2428                 :            :                 lval = AC97_AD1986_LVREF0;
    2429                 :            :                 mval = AC97_AD1986_MVREF0;
    2430                 :          0 :                 break;
    2431                 :            :         case 3: /* 0 V */
    2432                 :            :                 cval = AC97_AD1986_CVREF1;
    2433                 :            :                 lval = AC97_AD1986_LVREF1;
    2434                 :            :                 mval = AC97_AD1986_MVREF1;
    2435                 :          0 :                 break;
    2436                 :            :         default:
    2437                 :            :                 return -EINVAL;
    2438                 :            :         }
    2439                 :            : 
    2440                 :          0 :         cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
    2441                 :            :                                     AC97_AD1986_CVREF_MASK, cval);
    2442         [ #  # ]:          0 :         if (cret < 0)
    2443                 :            :                 return cret;
    2444                 :          0 :         lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3,
    2445                 :            :                                     AC97_AD1986_LVREF_MASK, lval);
    2446         [ #  # ]:          0 :         if (lret < 0)
    2447                 :            :                 return lret;
    2448                 :          0 :         mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
    2449                 :            :                                     AC97_AD1986_MVREF_MASK, mval);
    2450         [ #  # ]:          0 :         if (mret < 0)
    2451                 :            :                 return mret;
    2452                 :            : 
    2453 [ #  # ][ #  # ]:          0 :         return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0;
    2454                 :            : }
    2455                 :            : 
    2456                 :            : static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = {
    2457                 :            :         AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
    2458                 :            :         {
    2459                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2460                 :            :                 .name = "Exchange Front/Surround",
    2461                 :            :                 .info = snd_ac97_ad1986_bool_info,
    2462                 :            :                 .get = snd_ac97_ad1986_lososel_get,
    2463                 :            :                 .put = snd_ac97_ad1986_lososel_put
    2464                 :            :         },
    2465                 :            :         {
    2466                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2467                 :            :                 .name = "Exchange Mic/Line In",
    2468                 :            :                 .info = snd_ac97_ad1986_bool_info,
    2469                 :            :                 .get = snd_ac97_ad1986_miclisel_get,
    2470                 :            :                 .put = snd_ac97_ad1986_miclisel_put
    2471                 :            :         },
    2472                 :            :         {
    2473                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2474                 :            :                 .name = "Spread Front to Surround and Center/LFE",
    2475                 :            :                 .info = snd_ac97_ad1986_bool_info,
    2476                 :            :                 .get = snd_ac97_ad1986_spread_get,
    2477                 :            :                 .put = snd_ac97_ad1986_spread_put
    2478                 :            :         },
    2479                 :            :         {
    2480                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2481                 :            :                 .name = "Downmix",
    2482                 :            :                 .info = snd_ac97_ad1888_downmix_info,
    2483                 :            :                 .get = snd_ac97_ad1888_downmix_get,
    2484                 :            :                 .put = snd_ac97_ad1888_downmix_put
    2485                 :            :         },
    2486                 :            :         {
    2487                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2488                 :            :                 .name = "V_REFOUT",
    2489                 :            :                 .info = snd_ac97_ad1985_vrefout_info,
    2490                 :            :                 .get = snd_ac97_ad1986_vrefout_get,
    2491                 :            :                 .put = snd_ac97_ad1986_vrefout_put
    2492                 :            :         },
    2493                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    2494                 :            :         AC97_CHANNEL_MODE_CTL,
    2495                 :            : 
    2496                 :            :         AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
    2497                 :            :         AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0)
    2498                 :            : };
    2499                 :            : 
    2500                 :          0 : static void ad1986_update_jacks(struct snd_ac97 *ac97)
    2501                 :            : {
    2502                 :            :         unsigned short misc_val = 0;
    2503                 :            :         unsigned short ser_val;
    2504                 :            : 
    2505                 :            :         /* disable SURROUND and CENTER/LFE if not surround mode */
    2506         [ #  # ]:          0 :         if (!is_surround_on(ac97))
    2507                 :            :                 misc_val |= AC97_AD1986_SODIS;
    2508         [ #  # ]:          0 :         if (!is_clfe_on(ac97))
    2509                 :          0 :                 misc_val |= AC97_AD1986_CLDIS;
    2510                 :            : 
    2511                 :            :         /* select line input (default=LINE_IN, SURROUND or MIC_1/2) */
    2512         [ #  # ]:          0 :         if (is_shared_linein(ac97))
    2513                 :          0 :                 misc_val |= AC97_AD1986_LISEL_SURR;
    2514         [ #  # ]:          0 :         else if (ac97->spec.ad18xx.swap_mic_linein != 0)
    2515                 :          0 :                 misc_val |= AC97_AD1986_LISEL_MIC;
    2516                 :          0 :         snd_ac97_update_bits(ac97, AC97_AD_MISC,
    2517                 :            :                              AC97_AD1986_SODIS | AC97_AD1986_CLDIS |
    2518                 :            :                              AC97_AD1986_LISEL_MASK,
    2519                 :            :                              misc_val);
    2520                 :            : 
    2521                 :            :         /* select microphone input (MIC_1/2, Center/LFE or LINE_IN) */
    2522         [ #  # ]:          0 :         if (is_shared_micin(ac97))
    2523                 :            :                 ser_val = AC97_AD1986_OMS_C;
    2524         [ #  # ]:          0 :         else if (ac97->spec.ad18xx.swap_mic_linein != 0)
    2525                 :            :                 ser_val = AC97_AD1986_OMS_L;
    2526                 :            :         else
    2527                 :            :                 ser_val = AC97_AD1986_OMS_M;
    2528                 :          0 :         snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG,
    2529                 :            :                              AC97_AD1986_OMS_MASK,
    2530                 :            :                              ser_val);
    2531                 :          0 : }
    2532                 :            : 
    2533                 :          0 : static int patch_ad1986_specific(struct snd_ac97 *ac97)
    2534                 :            : {
    2535                 :            :         int err;
    2536                 :            : 
    2537         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
    2538                 :            :                 return err;
    2539                 :            : 
    2540                 :          0 :         return patch_build_controls(ac97, snd_ac97_ad1986_controls,
    2541                 :            :                                     ARRAY_SIZE(snd_ac97_ad1985_controls));
    2542                 :            : }
    2543                 :            : 
    2544                 :            : static const struct snd_ac97_build_ops patch_ad1986_build_ops = {
    2545                 :            :         .build_post_spdif = patch_ad198x_post_spdif,
    2546                 :            :         .build_specific = patch_ad1986_specific,
    2547                 :            : #ifdef CONFIG_PM
    2548                 :            :         .resume = ad18xx_resume,
    2549                 :            : #endif
    2550                 :            :         .update_jacks = ad1986_update_jacks,
    2551                 :            : };
    2552                 :            : 
    2553                 :          0 : static int patch_ad1986(struct snd_ac97 * ac97)
    2554                 :            : {
    2555                 :          0 :         patch_ad1881(ac97);
    2556                 :          0 :         ac97->build_ops = &patch_ad1986_build_ops;
    2557                 :          0 :         ac97->flags |= AC97_STEREO_MUTES;
    2558                 :            : 
    2559                 :            :         /* update current jack configuration */
    2560                 :          0 :         ad1986_update_jacks(ac97);
    2561                 :            : 
    2562                 :          0 :         return 0;
    2563                 :            : }
    2564                 :            : 
    2565                 :            : /*
    2566                 :            :  * realtek ALC203: use mono-out for pin 37
    2567                 :            :  */
    2568                 :          0 : static int patch_alc203(struct snd_ac97 *ac97)
    2569                 :            : {
    2570                 :          0 :         snd_ac97_update_bits(ac97, 0x7a, 0x400, 0x400);
    2571                 :          0 :         return 0;
    2572                 :            : }
    2573                 :            : 
    2574                 :            : /*
    2575                 :            :  * realtek ALC65x/850 codecs
    2576                 :            :  */
    2577                 :          0 : static void alc650_update_jacks(struct snd_ac97 *ac97)
    2578                 :            : {
    2579                 :            :         int shared;
    2580                 :            :         
    2581                 :            :         /* shared Line-In / Surround Out */
    2582                 :            :         shared = is_shared_surrout(ac97);
    2583         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
    2584                 :            :                              shared ? (1 << 9) : 0);
    2585                 :            :         /* update shared Mic In / Center/LFE Out */
    2586                 :            :         shared = is_shared_clfeout(ac97);
    2587                 :            :         /* disable/enable vref */
    2588         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
    2589                 :            :                              shared ? (1 << 12) : 0);
    2590                 :            :         /* turn on/off center-on-mic */
    2591         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
    2592                 :            :                              shared ? (1 << 10) : 0);
    2593                 :            :         /* GPIO0 high for mic */
    2594         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
    2595                 :            :                              shared ? 0 : 0x100);
    2596                 :          0 : }
    2597                 :            : 
    2598                 :          0 : static int alc650_swap_surround_put(struct snd_kcontrol *kcontrol,
    2599                 :            :                                     struct snd_ctl_elem_value *ucontrol)
    2600                 :            : {
    2601                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2602                 :          0 :         struct snd_pcm_chmap *map = ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK];
    2603                 :            : 
    2604         [ #  # ]:          0 :         if (map) {
    2605         [ #  # ]:          0 :                 if (ucontrol->value.integer.value[0])
    2606                 :          0 :                         map->chmap = snd_pcm_std_chmaps;
    2607                 :            :                 else
    2608                 :          0 :                         map->chmap = snd_pcm_alt_chmaps;
    2609                 :            :         }
    2610                 :          0 :         return snd_ac97_put_volsw(kcontrol, ucontrol);
    2611                 :            : }
    2612                 :            : 
    2613                 :            : static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
    2614                 :            :         AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
    2615                 :            :         AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
    2616                 :            :         AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
    2617                 :            :         AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
    2618                 :            :         /* 4: Analog Input To Surround */
    2619                 :            :         /* 5: Analog Input To Center/LFE */
    2620                 :            :         /* 6: Independent Master Volume Right */
    2621                 :            :         /* 7: Independent Master Volume Left */
    2622                 :            :         /* 8: reserved */
    2623                 :            :         /* 9: Line-In/Surround share */
    2624                 :            :         /* 10: Mic/CLFE share */
    2625                 :            :         /* 11-13: in IEC958 controls */
    2626                 :            :         {
    2627                 :            :                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    2628                 :            :                 .name = "Swap Surround Slot",
    2629                 :            :                 .info = snd_ac97_info_volsw,
    2630                 :            :                 .get = snd_ac97_get_volsw,
    2631                 :            :                 .put = alc650_swap_surround_put,
    2632                 :            :                 .private_value =  AC97_SINGLE_VALUE(AC97_ALC650_MULTICH, 14, 1, 0),
    2633                 :            :         },
    2634                 :            : #if 0 /* always set in patch_alc650 */
    2635                 :            :         AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
    2636                 :            :         AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
    2637                 :            :         AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
    2638                 :            :         AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
    2639                 :            :         AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
    2640                 :            :         AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
    2641                 :            : #endif
    2642                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    2643                 :            :         AC97_CHANNEL_MODE_CTL,
    2644                 :            : };
    2645                 :            : 
    2646                 :            : static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
    2647                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0),
    2648                 :            :         AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
    2649                 :            :         /* disable this controls since it doesn't work as expected */
    2650                 :            :         /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
    2651                 :            : };
    2652                 :            : 
    2653                 :            : static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
    2654                 :            : 
    2655                 :          0 : static int patch_alc650_specific(struct snd_ac97 * ac97)
    2656                 :            : {
    2657                 :            :         int err;
    2658                 :            : 
    2659         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650))) < 0)
    2660                 :            :                 return err;
    2661         [ #  # ]:          0 :         if (ac97->ext_id & AC97_EI_SPDIF) {
    2662         [ #  # ]:          0 :                 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
    2663                 :            :                         return err;
    2664                 :            :         }
    2665         [ #  # ]:          0 :         if (ac97->id != AC97_ID_ALC650F)
    2666                 :          0 :                 reset_tlv(ac97, "Master Playback Volume",
    2667                 :            :                           db_scale_5bit_3db_max);
    2668                 :            :         return 0;
    2669                 :            : }
    2670                 :            : 
    2671                 :            : static const struct snd_ac97_build_ops patch_alc650_ops = {
    2672                 :            :         .build_specific = patch_alc650_specific,
    2673                 :            :         .update_jacks = alc650_update_jacks
    2674                 :            : };
    2675                 :            : 
    2676                 :          0 : static int patch_alc650(struct snd_ac97 * ac97)
    2677                 :            : {
    2678                 :            :         unsigned short val;
    2679                 :            : 
    2680                 :          0 :         ac97->build_ops = &patch_alc650_ops;
    2681                 :            : 
    2682                 :            :         /* determine the revision */
    2683                 :          0 :         val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
    2684         [ #  # ]:          0 :         if (val < 3)
    2685                 :          0 :                 ac97->id = 0x414c4720;          /* Old version */
    2686         [ #  # ]:          0 :         else if (val < 0x10)
    2687                 :          0 :                 ac97->id = 0x414c4721;          /* D version */
    2688         [ #  # ]:          0 :         else if (val < 0x20)
    2689                 :          0 :                 ac97->id = 0x414c4722;          /* E version */
    2690         [ #  # ]:          0 :         else if (val < 0x30)
    2691                 :          0 :                 ac97->id = 0x414c4723;          /* F version */
    2692                 :            : 
    2693                 :            :         /* revision E or F */
    2694                 :            :         /* FIXME: what about revision D ? */
    2695                 :          0 :         ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
    2696                 :            :                                 ac97->id == 0x414c4723);
    2697                 :            : 
    2698                 :            :         /* enable AC97_ALC650_GPIO_SETUP, AC97_ALC650_CLOCK for R/W */
    2699                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS, 
    2700                 :          0 :                 snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
    2701                 :            : 
    2702                 :            :         /* Enable SPDIF-IN only on Rev.E and above */
    2703                 :          0 :         val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
    2704                 :            :         /* SPDIF IN with pin 47 */
    2705 [ #  # ][ #  # ]:          0 :         if (ac97->spec.dev_flags &&
    2706                 :            :             /* ASUS A6KM requires EAPD */
    2707                 :          0 :             ! (ac97->subsystem_vendor == 0x1043 &&
    2708                 :            :                ac97->subsystem_device == 0x1103))
    2709                 :          0 :                 val |= 0x03; /* enable */
    2710                 :            :         else
    2711                 :          0 :                 val &= ~0x03; /* disable */
    2712                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val);
    2713                 :            : 
    2714                 :            :         /* set default: slot 3,4,7,8,6,9
    2715                 :            :            spdif-in monitor off, analog-spdif off, spdif-in off
    2716                 :            :            center on mic off, surround on line-in off
    2717                 :            :            downmix off, duplicate front off
    2718                 :            :         */
    2719                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 0);
    2720                 :            : 
    2721                 :            :         /* set GPIO0 for mic bias */
    2722                 :            :         /* GPIO0 pin output, no interrupt, high */
    2723                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP,
    2724                 :          0 :                              snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01);
    2725                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
    2726                 :          0 :                              (snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100) & ~0x10);
    2727                 :            : 
    2728                 :            :         /* full DAC volume */
    2729                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
    2730                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
    2731                 :          0 :         return 0;
    2732                 :            : }
    2733                 :            : 
    2734                 :          0 : static void alc655_update_jacks(struct snd_ac97 *ac97)
    2735                 :            : {
    2736                 :            :         int shared;
    2737                 :            :         
    2738                 :            :         /* shared Line-In / Surround Out */
    2739                 :            :         shared = is_shared_surrout(ac97);
    2740         [ #  # ]:          0 :         ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
    2741                 :            :                               shared ? (1 << 9) : 0, 0);
    2742                 :            :         /* update shared Mic In / Center/LFE Out */
    2743                 :            :         shared = is_shared_clfeout(ac97);
    2744                 :            :         /* misc control; vrefout disable */
    2745         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
    2746                 :            :                              shared ? (1 << 12) : 0);
    2747         [ #  # ]:          0 :         ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
    2748                 :            :                               shared ? (1 << 10) : 0, 0);
    2749                 :          0 : }
    2750                 :            : 
    2751                 :            : static const struct snd_kcontrol_new snd_ac97_controls_alc655[] = {
    2752                 :            :         AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
    2753                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    2754                 :            :         AC97_CHANNEL_MODE_CTL,
    2755                 :            : };
    2756                 :            : 
    2757                 :          0 : static int alc655_iec958_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    2758                 :            : {
    2759                 :            :         static char *texts_655[3] = { "PCM", "Analog In", "IEC958 In" };
    2760                 :            :         static char *texts_658[4] = { "PCM", "Analog1 In", "Analog2 In", "IEC958 In" };
    2761                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2762                 :            : 
    2763                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
    2764                 :          0 :         uinfo->count = 1;
    2765         [ #  # ]:          0 :         uinfo->value.enumerated.items = ac97->spec.dev_flags ? 4 : 3;
    2766         [ #  # ]:          0 :         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
    2767                 :          0 :                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
    2768         [ #  # ]:          0 :         strcpy(uinfo->value.enumerated.name,
    2769                 :          0 :                ac97->spec.dev_flags ?
    2770                 :          0 :                texts_658[uinfo->value.enumerated.item] :
    2771                 :          0 :                texts_655[uinfo->value.enumerated.item]);
    2772                 :          0 :         return 0;
    2773                 :            : }
    2774                 :            : 
    2775                 :          0 : static int alc655_iec958_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    2776                 :            : {
    2777                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2778                 :            :         unsigned short val;
    2779                 :            : 
    2780                 :          0 :         val = ac97->regs[AC97_ALC650_MULTICH];
    2781                 :          0 :         val = (val >> 12) & 3;
    2782 [ #  # ][ #  # ]:          0 :         if (ac97->spec.dev_flags && val == 3)
    2783                 :            :                 val = 0;
    2784                 :          0 :         ucontrol->value.enumerated.item[0] = val;
    2785                 :          0 :         return 0;
    2786                 :            : }
    2787                 :            : 
    2788                 :          0 : static int alc655_iec958_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    2789                 :            : {
    2790                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    2791                 :            : 
    2792                 :          0 :         return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
    2793                 :          0 :                                      (unsigned short)ucontrol->value.enumerated.item[0] << 12,
    2794                 :            :                                      0);
    2795                 :            : }
    2796                 :            : 
    2797                 :            : static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc655[] = {
    2798                 :            :         AC97_PAGE_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_ALC650_MULTICH, 11, 1, 0, 0),
    2799                 :            :         /* disable this controls since it doesn't work as expected */
    2800                 :            :         /* AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0), */
    2801                 :            :         {
    2802                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
    2803                 :            :                 .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
    2804                 :            :                 .info   = alc655_iec958_route_info,
    2805                 :            :                 .get    = alc655_iec958_route_get,
    2806                 :            :                 .put    = alc655_iec958_route_put,
    2807                 :            :         },
    2808                 :            : };
    2809                 :            : 
    2810                 :          0 : static int patch_alc655_specific(struct snd_ac97 * ac97)
    2811                 :            : {
    2812                 :            :         int err;
    2813                 :            : 
    2814         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655))) < 0)
    2815                 :            :                 return err;
    2816         [ #  # ]:          0 :         if (ac97->ext_id & AC97_EI_SPDIF) {
    2817         [ #  # ]:          0 :                 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
    2818                 :          0 :                         return err;
    2819                 :            :         }
    2820                 :            :         return 0;
    2821                 :            : }
    2822                 :            : 
    2823                 :            : static const struct snd_ac97_build_ops patch_alc655_ops = {
    2824                 :            :         .build_specific = patch_alc655_specific,
    2825                 :            :         .update_jacks = alc655_update_jacks
    2826                 :            : };
    2827                 :            : 
    2828                 :          0 : static int patch_alc655(struct snd_ac97 * ac97)
    2829                 :            : {
    2830                 :            :         unsigned int val;
    2831                 :            : 
    2832         [ #  # ]:          0 :         if (ac97->id == AC97_ID_ALC658) {
    2833                 :          0 :                 ac97->spec.dev_flags = 1; /* ALC658 */
    2834         [ #  # ]:          0 :                 if ((snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f) == 2) {
    2835                 :          0 :                         ac97->id = AC97_ID_ALC658D;
    2836                 :          0 :                         ac97->spec.dev_flags = 2;
    2837                 :            :                 }
    2838                 :            :         }
    2839                 :            : 
    2840                 :          0 :         ac97->build_ops = &patch_alc655_ops;
    2841                 :            : 
    2842                 :            :         /* assume only page 0 for writing cache */
    2843                 :          0 :         snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
    2844                 :            : 
    2845                 :            :         /* adjust default values */
    2846                 :          0 :         val = snd_ac97_read(ac97, 0x7a); /* misc control */
    2847         [ #  # ]:          0 :         if (ac97->spec.dev_flags) /* ALC658 */
    2848                 :          0 :                 val &= ~(1 << 1); /* Pin 47 is spdif input pin */
    2849                 :            :         else { /* ALC655 */
    2850 [ #  # ][ #  # ]:          0 :                 if (ac97->subsystem_vendor == 0x1462 &&
    2851                 :          0 :                     (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */
    2852         [ #  # ]:          0 :                      ac97->subsystem_device == 0x0161 || /* LG K1 Express */
    2853         [ #  # ]:          0 :                      ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */
    2854         [ #  # ]:          0 :                      ac97->subsystem_device == 0x0471 || /* MSI L720 laptop */
    2855                 :            :                      ac97->subsystem_device == 0x0061))  /* MSI S250 laptop */
    2856                 :          0 :                         val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
    2857                 :            :                 else
    2858                 :          0 :                         val |= (1 << 1); /* Pin 47 is spdif input pin */
    2859                 :            :                 /* this seems missing on some hardwares */
    2860                 :          0 :                 ac97->ext_id |= AC97_EI_SPDIF;
    2861                 :            :         }
    2862                 :          0 :         val &= ~(1 << 12); /* vref enable */
    2863                 :          0 :         snd_ac97_write_cache(ac97, 0x7a, val);
    2864                 :            :         /* set default: spdif-in enabled,
    2865                 :            :            spdif-in monitor off, spdif-in PCM off
    2866                 :            :            center on mic off, surround on line-in off
    2867                 :            :            duplicate front off
    2868                 :            :         */
    2869                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
    2870                 :            : 
    2871                 :            :         /* full DAC volume */
    2872                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
    2873                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
    2874                 :            : 
    2875                 :            :         /* update undocumented bit... */
    2876         [ #  # ]:          0 :         if (ac97->id == AC97_ID_ALC658D)
    2877                 :          0 :                 snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
    2878                 :            : 
    2879                 :          0 :         return 0;
    2880                 :            : }
    2881                 :            : 
    2882                 :            : 
    2883                 :            : #define AC97_ALC850_JACK_SELECT 0x76
    2884                 :            : #define AC97_ALC850_MISC1       0x7a
    2885                 :            : #define AC97_ALC850_MULTICH    0x6a
    2886                 :            : 
    2887                 :          0 : static void alc850_update_jacks(struct snd_ac97 *ac97)
    2888                 :            : {
    2889                 :            :         int shared;
    2890                 :            :         int aux_is_back_surround;
    2891                 :            :         
    2892                 :            :         /* shared Line-In / Surround Out */
    2893                 :            :         shared = is_shared_surrout(ac97);
    2894                 :            :         /* SURR 1kOhm (bit4), Amp (bit5) */
    2895         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
    2896                 :            :                              shared ? (1<<5) : (1<<4));
    2897                 :            :         /* LINE-IN = 0, SURROUND = 2 */
    2898         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
    2899                 :            :                              shared ? (2<<12) : (0<<12));
    2900                 :            :         /* update shared Mic In / Center/LFE Out */
    2901                 :            :         shared = is_shared_clfeout(ac97);
    2902                 :            :         /* Vref disable (bit12), 1kOhm (bit13) */
    2903         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
    2904                 :            :                              shared ? (1<<12) : (1<<13));
    2905                 :            :         /* MIC-IN = 1, CENTER-LFE = 5 */
    2906         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
    2907                 :            :                              shared ? (5<<4) : (1<<4));
    2908                 :            : 
    2909                 :            :         aux_is_back_surround = alc850_is_aux_back_surround(ac97);
    2910                 :            :         /* Aux is Back Surround */
    2911         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10,
    2912                 :            :                                  aux_is_back_surround ? (1<<10) : (0<<10));
    2913                 :          0 : }
    2914                 :            : 
    2915                 :            : static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
    2916                 :            :         AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
    2917                 :            :         AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
    2918                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    2919                 :            :         AC97_CHANNEL_MODE_8CH_CTL,
    2920                 :            : };
    2921                 :            : 
    2922                 :          0 : static int patch_alc850_specific(struct snd_ac97 *ac97)
    2923                 :            : {
    2924                 :            :         int err;
    2925                 :            : 
    2926         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0)
    2927                 :            :                 return err;
    2928         [ #  # ]:          0 :         if (ac97->ext_id & AC97_EI_SPDIF) {
    2929         [ #  # ]:          0 :                 if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
    2930                 :          0 :                         return err;
    2931                 :            :         }
    2932                 :            :         return 0;
    2933                 :            : }
    2934                 :            : 
    2935                 :            : static const struct snd_ac97_build_ops patch_alc850_ops = {
    2936                 :            :         .build_specific = patch_alc850_specific,
    2937                 :            :         .update_jacks = alc850_update_jacks
    2938                 :            : };
    2939                 :            : 
    2940                 :          0 : static int patch_alc850(struct snd_ac97 *ac97)
    2941                 :            : {
    2942                 :          0 :         ac97->build_ops = &patch_alc850_ops;
    2943                 :            : 
    2944                 :          0 :         ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
    2945                 :          0 :         ac97->flags |= AC97_HAS_8CH;
    2946                 :            : 
    2947                 :            :         /* assume only page 0 for writing cache */
    2948                 :          0 :         snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
    2949                 :            : 
    2950                 :            :         /* adjust default values */
    2951                 :            :         /* set default: spdif-in enabled,
    2952                 :            :            spdif-in monitor off, spdif-in PCM off
    2953                 :            :            center on mic off, surround on line-in off
    2954                 :            :            duplicate front off
    2955                 :            :            NB default bit 10=0 = Aux is Capture, not Back Surround
    2956                 :            :         */
    2957                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
    2958                 :            :         /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
    2959                 :            :          * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on
    2960                 :            :          */
    2961                 :          0 :         snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
    2962                 :            :                              (1<<7)|(0<<12)|(1<<13)|(0<<14));
    2963                 :            :         /* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable,
    2964                 :            :          * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute
    2965                 :            :          */
    2966                 :          0 :         snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
    2967                 :            :                              (1<<11)|(0<<12)|(1<<15));
    2968                 :            : 
    2969                 :            :         /* full DAC volume */
    2970                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
    2971                 :          0 :         snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
    2972                 :          0 :         return 0;
    2973                 :            : }
    2974                 :            : 
    2975                 :          0 : static int patch_aztech_azf3328_specific(struct snd_ac97 *ac97)
    2976                 :            : {
    2977                 :          0 :         struct snd_kcontrol *kctl_3d_center =
    2978                 :            :                 snd_ac97_find_mixer_ctl(ac97, "3D Control - Center");
    2979                 :          0 :         struct snd_kcontrol *kctl_3d_depth =
    2980                 :            :                 snd_ac97_find_mixer_ctl(ac97, "3D Control - Depth");
    2981                 :            : 
    2982                 :            :         /*
    2983                 :            :          * 3D register is different from AC97 standard layout
    2984                 :            :          * (also do some renaming, to resemble Windows driver naming)
    2985                 :            :          */
    2986         [ #  # ]:          0 :         if (kctl_3d_center) {
    2987                 :          0 :                 kctl_3d_center->private_value =
    2988                 :            :                         AC97_SINGLE_VALUE(AC97_3D_CONTROL, 1, 0x07, 0);
    2989                 :          0 :                 snd_ac97_rename_vol_ctl(ac97,
    2990                 :            :                         "3D Control - Center", "3D Control - Width"
    2991                 :            :                 );
    2992                 :            :         }
    2993         [ #  # ]:          0 :         if (kctl_3d_depth)
    2994                 :          0 :                 kctl_3d_depth->private_value =
    2995                 :            :                         AC97_SINGLE_VALUE(AC97_3D_CONTROL, 8, 0x03, 0);
    2996                 :            : 
    2997                 :            :         /* Aztech Windows driver calls the
    2998                 :            :            equivalent control "Modem Playback", thus rename it: */
    2999                 :          0 :         snd_ac97_rename_vol_ctl(ac97,
    3000                 :            :                 "Master Mono Playback", "Modem Playback"
    3001                 :            :         );
    3002                 :          0 :         snd_ac97_rename_vol_ctl(ac97,
    3003                 :            :                 "Headphone Playback", "FM Synth Playback"
    3004                 :            :         );
    3005                 :            : 
    3006                 :          0 :         return 0;
    3007                 :            : }
    3008                 :            : 
    3009                 :            : static const struct snd_ac97_build_ops patch_aztech_azf3328_ops = {
    3010                 :            :         .build_specific = patch_aztech_azf3328_specific
    3011                 :            : };
    3012                 :            : 
    3013                 :          0 : static int patch_aztech_azf3328(struct snd_ac97 *ac97)
    3014                 :            : {
    3015                 :          0 :         ac97->build_ops = &patch_aztech_azf3328_ops;
    3016                 :          0 :         return 0;
    3017                 :            : }
    3018                 :            : 
    3019                 :            : /*
    3020                 :            :  * C-Media CM97xx codecs
    3021                 :            :  */
    3022                 :          0 : static void cm9738_update_jacks(struct snd_ac97 *ac97)
    3023                 :            : {
    3024                 :            :         /* shared Line-In / Surround Out */
    3025         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
    3026                 :            :                              is_shared_surrout(ac97) ? (1 << 10) : 0);
    3027                 :          0 : }
    3028                 :            : 
    3029                 :            : static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
    3030                 :            :         AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
    3031                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    3032                 :            :         AC97_CHANNEL_MODE_4CH_CTL,
    3033                 :            : };
    3034                 :            : 
    3035                 :          0 : static int patch_cm9738_specific(struct snd_ac97 * ac97)
    3036                 :            : {
    3037                 :          0 :         return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
    3038                 :            : }
    3039                 :            : 
    3040                 :            : static const struct snd_ac97_build_ops patch_cm9738_ops = {
    3041                 :            :         .build_specific = patch_cm9738_specific,
    3042                 :            :         .update_jacks = cm9738_update_jacks
    3043                 :            : };
    3044                 :            : 
    3045                 :          0 : static int patch_cm9738(struct snd_ac97 * ac97)
    3046                 :            : {
    3047                 :          0 :         ac97->build_ops = &patch_cm9738_ops;
    3048                 :            :         /* FIXME: can anyone confirm below? */
    3049                 :            :         /* CM9738 has no PCM volume although the register reacts */
    3050                 :          0 :         ac97->flags |= AC97_HAS_NO_PCM_VOL;
    3051                 :          0 :         snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
    3052                 :            : 
    3053                 :          0 :         return 0;
    3054                 :            : }
    3055                 :            : 
    3056                 :          0 : static int snd_ac97_cmedia_spdif_playback_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    3057                 :            : {
    3058                 :            :         static char *texts[] = { "Analog", "Digital" };
    3059                 :            : 
    3060                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
    3061                 :          0 :         uinfo->count = 1;
    3062                 :          0 :         uinfo->value.enumerated.items = 2;
    3063         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 1)
    3064                 :          0 :                 uinfo->value.enumerated.item = 1;
    3065                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
    3066                 :          0 :         return 0;
    3067                 :            : }
    3068                 :            : 
    3069                 :          0 : static int snd_ac97_cmedia_spdif_playback_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    3070                 :            : {
    3071                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    3072                 :            :         unsigned short val;
    3073                 :            : 
    3074                 :          0 :         val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
    3075                 :          0 :         ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
    3076                 :          0 :         return 0;
    3077                 :            : }
    3078                 :            : 
    3079                 :          0 : static int snd_ac97_cmedia_spdif_playback_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    3080                 :            : {
    3081                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    3082                 :            : 
    3083                 :          0 :         return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
    3084                 :            :                                     0x01 << 1, 
    3085                 :          0 :                                     (ucontrol->value.enumerated.item[0] & 0x01) << 1);
    3086                 :            : }
    3087                 :            : 
    3088                 :            : static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = {
    3089                 :            :         /* BIT 0: SPDI_EN - always true */
    3090                 :            :         { /* BIT 1: SPDIFS */
    3091                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
    3092                 :            :                 .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
    3093                 :            :                 .info   = snd_ac97_cmedia_spdif_playback_source_info,
    3094                 :            :                 .get    = snd_ac97_cmedia_spdif_playback_source_get,
    3095                 :            :                 .put    = snd_ac97_cmedia_spdif_playback_source_put,
    3096                 :            :         },
    3097                 :            :         /* BIT 2: IG_SPIV */
    3098                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
    3099                 :            :         /* BIT 3: SPI2F */
    3100                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0), 
    3101                 :            :         /* BIT 4: SPI2SDI */
    3102                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
    3103                 :            :         /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
    3104                 :            : };
    3105                 :            : 
    3106                 :          0 : static void cm9739_update_jacks(struct snd_ac97 *ac97)
    3107                 :            : {
    3108                 :            :         /* shared Line-In / Surround Out */
    3109         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
    3110                 :            :                              is_shared_surrout(ac97) ? (1 << 10) : 0);
    3111                 :            :         /* shared Mic In / Center/LFE Out **/
    3112         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
    3113                 :            :                              is_shared_clfeout(ac97) ? 0x1000 : 0x2000);
    3114                 :          0 : }
    3115                 :            : 
    3116                 :            : static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
    3117                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    3118                 :            :         AC97_CHANNEL_MODE_CTL,
    3119                 :            : };
    3120                 :            : 
    3121                 :          0 : static int patch_cm9739_specific(struct snd_ac97 * ac97)
    3122                 :            : {
    3123                 :          0 :         return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
    3124                 :            : }
    3125                 :            : 
    3126                 :          0 : static int patch_cm9739_post_spdif(struct snd_ac97 * ac97)
    3127                 :            : {
    3128                 :          0 :         return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
    3129                 :            : }
    3130                 :            : 
    3131                 :            : static const struct snd_ac97_build_ops patch_cm9739_ops = {
    3132                 :            :         .build_specific = patch_cm9739_specific,
    3133                 :            :         .build_post_spdif = patch_cm9739_post_spdif,
    3134                 :            :         .update_jacks = cm9739_update_jacks
    3135                 :            : };
    3136                 :            : 
    3137                 :          0 : static int patch_cm9739(struct snd_ac97 * ac97)
    3138                 :            : {
    3139                 :            :         unsigned short val;
    3140                 :            : 
    3141                 :          0 :         ac97->build_ops = &patch_cm9739_ops;
    3142                 :            : 
    3143                 :            :         /* CM9739/A has no Master and PCM volume although the register reacts */
    3144                 :          0 :         ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;
    3145                 :          0 :         snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);
    3146                 :          0 :         snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
    3147                 :            : 
    3148                 :            :         /* check spdif */
    3149                 :          0 :         val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
    3150         [ #  # ]:          0 :         if (val & AC97_EA_SPCV) {
    3151                 :            :                 /* enable spdif in */
    3152                 :          0 :                 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
    3153                 :          0 :                                      snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
    3154                 :          0 :                 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
    3155                 :            :         } else {
    3156                 :          0 :                 ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */
    3157                 :          0 :                 ac97->rates[AC97_RATES_SPDIF] = 0;
    3158                 :            :         }
    3159                 :            : 
    3160                 :            :         /* set-up multi channel */
    3161                 :            :         /* bit 14: 0 = SPDIF, 1 = EAPD */
    3162                 :            :         /* bit 13: enable internal vref output for mic */
    3163                 :            :         /* bit 12: disable center/lfe (swithable) */
    3164                 :            :         /* bit 10: disable surround/line (switchable) */
    3165                 :            :         /* bit 9: mix 2 surround off */
    3166                 :            :         /* bit 4: undocumented; 0 mutes the CM9739A, which defaults to 1 */
    3167                 :            :         /* bit 3: undocumented; surround? */
    3168                 :            :         /* bit 0: dB */
    3169                 :          0 :         val = snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) & (1 << 4);
    3170                 :            :         val |= (1 << 3);
    3171                 :          0 :         val |= (1 << 13);
    3172         [ #  # ]:          0 :         if (! (ac97->ext_id & AC97_EI_SPDIF))
    3173                 :          0 :                 val |= (1 << 14);
    3174                 :          0 :         snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);
    3175                 :            : 
    3176                 :            :         /* FIXME: set up GPIO */
    3177                 :          0 :         snd_ac97_write_cache(ac97, 0x70, 0x0100);
    3178                 :          0 :         snd_ac97_write_cache(ac97, 0x72, 0x0020);
    3179                 :            :         /* Special exception for ASUS W1000/CMI9739. It does not have an SPDIF in. */
    3180         [ #  # ]:          0 :         if (ac97->pci &&
    3181         [ #  # ]:          0 :              ac97->subsystem_vendor == 0x1043 &&
    3182                 :            :              ac97->subsystem_device == 0x1843) {
    3183                 :          0 :                 snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
    3184                 :          0 :                         snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) & ~0x01);
    3185                 :          0 :                 snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN,
    3186                 :          0 :                         snd_ac97_read(ac97, AC97_CM9739_MULTI_CHAN) | (1 << 14));
    3187                 :            :         }
    3188                 :            : 
    3189                 :          0 :         return 0;
    3190                 :            : }
    3191                 :            : 
    3192                 :            : #define AC97_CM9761_MULTI_CHAN  0x64
    3193                 :            : #define AC97_CM9761_FUNC        0x66
    3194                 :            : #define AC97_CM9761_SPDIF_CTRL  0x6c
    3195                 :            : 
    3196                 :          0 : static void cm9761_update_jacks(struct snd_ac97 *ac97)
    3197                 :            : {
    3198                 :            :         /* FIXME: check the bits for each model
    3199                 :            :          *        model 83 is confirmed to work
    3200                 :            :          */
    3201                 :            :         static unsigned short surr_on[3][2] = {
    3202                 :            :                 { 0x0008, 0x0000 }, /* 9761-78 & 82 */
    3203                 :            :                 { 0x0000, 0x0008 }, /* 9761-82 rev.B */
    3204                 :            :                 { 0x0000, 0x0008 }, /* 9761-83 */
    3205                 :            :         };
    3206                 :            :         static unsigned short clfe_on[3][2] = {
    3207                 :            :                 { 0x0000, 0x1000 }, /* 9761-78 & 82 */
    3208                 :            :                 { 0x1000, 0x0000 }, /* 9761-82 rev.B */
    3209                 :            :                 { 0x0000, 0x1000 }, /* 9761-83 */
    3210                 :            :         };
    3211                 :            :         static unsigned short surr_shared[3][2] = {
    3212                 :            :                 { 0x0000, 0x0400 }, /* 9761-78 & 82 */
    3213                 :            :                 { 0x0000, 0x0400 }, /* 9761-82 rev.B */
    3214                 :            :                 { 0x0000, 0x0400 }, /* 9761-83 */
    3215                 :            :         };
    3216                 :            :         static unsigned short clfe_shared[3][2] = {
    3217                 :            :                 { 0x2000, 0x0880 }, /* 9761-78 & 82 */
    3218                 :            :                 { 0x0000, 0x2880 }, /* 9761-82 rev.B */
    3219                 :            :                 { 0x2000, 0x0800 }, /* 9761-83 */
    3220                 :            :         };
    3221                 :            :         unsigned short val = 0;
    3222                 :            : 
    3223                 :          0 :         val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
    3224                 :          0 :         val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
    3225                 :          0 :         val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)];
    3226                 :          0 :         val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)];
    3227                 :            : 
    3228                 :          0 :         snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
    3229                 :          0 : }
    3230                 :            : 
    3231                 :            : static const struct snd_kcontrol_new snd_ac97_cm9761_controls[] = {
    3232                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    3233                 :            :         AC97_CHANNEL_MODE_CTL,
    3234                 :            : };
    3235                 :            : 
    3236                 :          0 : static int cm9761_spdif_out_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
    3237                 :            : {
    3238                 :            :         static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" };
    3239                 :            : 
    3240                 :          0 :         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
    3241                 :          0 :         uinfo->count = 1;
    3242                 :          0 :         uinfo->value.enumerated.items = 3;
    3243         [ #  # ]:          0 :         if (uinfo->value.enumerated.item > 2)
    3244                 :          0 :                 uinfo->value.enumerated.item = 2;
    3245                 :          0 :         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
    3246                 :          0 :         return 0;
    3247                 :            : }
    3248                 :            : 
    3249                 :          0 : static int cm9761_spdif_out_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    3250                 :            : {
    3251                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    3252                 :            : 
    3253         [ #  # ]:          0 :         if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
    3254                 :          0 :                 ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */
    3255         [ #  # ]:          0 :         else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
    3256                 :          0 :                 ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */
    3257                 :            :         else
    3258                 :          0 :                 ucontrol->value.enumerated.item[0] = 0; /* AC-link */
    3259                 :          0 :         return 0;
    3260                 :            : }
    3261                 :            : 
    3262                 :          0 : static int cm9761_spdif_out_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
    3263                 :            : {
    3264                 :          0 :         struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
    3265                 :            : 
    3266         [ #  # ]:          0 :         if (ucontrol->value.enumerated.item[0] == 2)
    3267                 :          0 :                 return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
    3268                 :          0 :         snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
    3269         [ #  # ]:          0 :         return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
    3270                 :          0 :                                     ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
    3271                 :            : }
    3272                 :            : 
    3273                 :            : static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" };
    3274                 :            : static const struct ac97_enum cm9761_dac_clock_enum =
    3275                 :            :         AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
    3276                 :            : 
    3277                 :            : static const struct snd_kcontrol_new snd_ac97_cm9761_controls_spdif[] = {
    3278                 :            :         { /* BIT 1: SPDIFS */
    3279                 :            :                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
    3280                 :            :                 .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
    3281                 :            :                 .info = cm9761_spdif_out_source_info,
    3282                 :            :                 .get = cm9761_spdif_out_source_get,
    3283                 :            :                 .put = cm9761_spdif_out_source_put,
    3284                 :            :         },
    3285                 :            :         /* BIT 2: IG_SPIV */
    3286                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
    3287                 :            :         /* BIT 3: SPI2F */
    3288                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0), 
    3289                 :            :         /* BIT 4: SPI2SDI */
    3290                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
    3291                 :            :         /* BIT 9-10: DAC_CTL */
    3292                 :            :         AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
    3293                 :            : };
    3294                 :            : 
    3295                 :          0 : static int patch_cm9761_post_spdif(struct snd_ac97 * ac97)
    3296                 :            : {
    3297                 :          0 :         return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
    3298                 :            : }
    3299                 :            : 
    3300                 :          0 : static int patch_cm9761_specific(struct snd_ac97 * ac97)
    3301                 :            : {
    3302                 :          0 :         return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
    3303                 :            : }
    3304                 :            : 
    3305                 :            : static const struct snd_ac97_build_ops patch_cm9761_ops = {
    3306                 :            :         .build_specific = patch_cm9761_specific,
    3307                 :            :         .build_post_spdif = patch_cm9761_post_spdif,
    3308                 :            :         .update_jacks = cm9761_update_jacks
    3309                 :            : };
    3310                 :            : 
    3311                 :          0 : static int patch_cm9761(struct snd_ac97 *ac97)
    3312                 :            : {
    3313                 :            :         unsigned short val;
    3314                 :            : 
    3315                 :            :         /* CM9761 has no PCM volume although the register reacts */
    3316                 :            :         /* Master volume seems to have _some_ influence on the analog
    3317                 :            :          * input sounds
    3318                 :            :          */
    3319                 :          0 :         ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL;
    3320                 :          0 :         snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
    3321                 :          0 :         snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
    3322                 :            : 
    3323                 :          0 :         ac97->spec.dev_flags = 0; /* 1 = model 82 revision B, 2 = model 83 */
    3324         [ #  # ]:          0 :         if (ac97->id == AC97_ID_CM9761_82) {
    3325                 :            :                 unsigned short tmp;
    3326                 :            :                 /* check page 1, reg 0x60 */
    3327                 :          0 :                 val = snd_ac97_read(ac97, AC97_INT_PAGING);
    3328                 :          0 :                 snd_ac97_write_cache(ac97, AC97_INT_PAGING, (val & ~0x0f) | 0x01);
    3329                 :          0 :                 tmp = snd_ac97_read(ac97, 0x60);
    3330                 :          0 :                 ac97->spec.dev_flags = tmp & 1; /* revision B? */
    3331                 :          0 :                 snd_ac97_write_cache(ac97, AC97_INT_PAGING, val);
    3332         [ #  # ]:          0 :         } else if (ac97->id == AC97_ID_CM9761_83)
    3333                 :          0 :                 ac97->spec.dev_flags = 2;
    3334                 :            : 
    3335                 :          0 :         ac97->build_ops = &patch_cm9761_ops;
    3336                 :            : 
    3337                 :            :         /* enable spdif */
    3338                 :            :         /* force the SPDIF bit in ext_id - codec doesn't set this bit! */
    3339                 :          0 :         ac97->ext_id |= AC97_EI_SPDIF;
    3340                 :            :         /* to be sure: we overwrite the ext status bits */
    3341                 :          0 :         snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
    3342                 :            :         /* Don't set 0x0200 here.  This results in the silent analog output */
    3343                 :          0 :         snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */
    3344                 :          0 :         ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
    3345                 :            : 
    3346                 :            :         /* set-up multi channel */
    3347                 :            :         /* bit 15: pc master beep off
    3348                 :            :          * bit 14: pin47 = EAPD/SPDIF
    3349                 :            :          * bit 13: vref ctl [= cm9739]
    3350                 :            :          * bit 12: CLFE control (reverted on rev B)
    3351                 :            :          * bit 11: Mic/center share (reverted on rev B)
    3352                 :            :          * bit 10: suddound/line share
    3353                 :            :          * bit  9: Analog-in mix -> surround
    3354                 :            :          * bit  8: Analog-in mix -> CLFE
    3355                 :            :          * bit  7: Mic/LFE share (mic/center/lfe)
    3356                 :            :          * bit  5: vref select (9761A)
    3357                 :            :          * bit  4: front control
    3358                 :            :          * bit  3: surround control (revereted with rev B)
    3359                 :            :          * bit  2: front mic
    3360                 :            :          * bit  1: stereo mic
    3361                 :            :          * bit  0: mic boost level (0=20dB, 1=30dB)
    3362                 :            :          */
    3363                 :            : 
    3364                 :            : #if 0
    3365                 :            :         if (ac97->spec.dev_flags)
    3366                 :            :                 val = 0x0214;
    3367                 :            :         else
    3368                 :            :                 val = 0x321c;
    3369                 :            : #endif
    3370                 :          0 :         val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN);
    3371                 :          0 :         val |= (1 << 4); /* front on */
    3372                 :          0 :         snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
    3373                 :            : 
    3374                 :            :         /* FIXME: set up GPIO */
    3375                 :          0 :         snd_ac97_write_cache(ac97, 0x70, 0x0100);
    3376                 :          0 :         snd_ac97_write_cache(ac97, 0x72, 0x0020);
    3377                 :            : 
    3378                 :          0 :         return 0;
    3379                 :            : }
    3380                 :            :        
    3381                 :            : #define AC97_CM9780_SIDE        0x60
    3382                 :            : #define AC97_CM9780_JACK        0x62
    3383                 :            : #define AC97_CM9780_MIXER       0x64
    3384                 :            : #define AC97_CM9780_MULTI_CHAN  0x66
    3385                 :            : #define AC97_CM9780_SPDIF       0x6c
    3386                 :            : 
    3387                 :            : static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" };
    3388                 :            : static const struct ac97_enum cm9780_ch_select_enum =
    3389                 :            :         AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
    3390                 :            : static const struct snd_kcontrol_new cm9780_controls[] = {
    3391                 :            :         AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
    3392                 :            :         AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
    3393                 :            :         AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
    3394                 :            : };
    3395                 :            : 
    3396                 :          0 : static int patch_cm9780_specific(struct snd_ac97 *ac97)
    3397                 :            : {
    3398                 :          0 :         return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
    3399                 :            : }
    3400                 :            : 
    3401                 :            : static const struct snd_ac97_build_ops patch_cm9780_ops = {
    3402                 :            :         .build_specific = patch_cm9780_specific,
    3403                 :            :         .build_post_spdif = patch_cm9761_post_spdif     /* identical with CM9761 */
    3404                 :            : };
    3405                 :            : 
    3406                 :          0 : static int patch_cm9780(struct snd_ac97 *ac97)
    3407                 :            : {
    3408                 :            :         unsigned short val;
    3409                 :            : 
    3410                 :          0 :         ac97->build_ops = &patch_cm9780_ops;
    3411                 :            : 
    3412                 :            :         /* enable spdif */
    3413         [ #  # ]:          0 :         if (ac97->ext_id & AC97_EI_SPDIF) {
    3414                 :          0 :                 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
    3415                 :          0 :                 val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
    3416                 :          0 :                 val |= 0x1; /* SPDI_EN */
    3417                 :          0 :                 snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
    3418                 :            :         }
    3419                 :            : 
    3420                 :          0 :         return 0;
    3421                 :            : }
    3422                 :            : 
    3423                 :            : /*
    3424                 :            :  * VIA VT1616 codec
    3425                 :            :  */
    3426                 :            : static const struct snd_kcontrol_new snd_ac97_controls_vt1616[] = {
    3427                 :            : AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
    3428                 :            : AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
    3429                 :            : AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
    3430                 :            : AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
    3431                 :            : };
    3432                 :            : 
    3433                 :            : static const char *slave_vols_vt1616[] = {
    3434                 :            :         "Front Playback Volume",
    3435                 :            :         "Surround Playback Volume",
    3436                 :            :         "Center Playback Volume",
    3437                 :            :         "LFE Playback Volume",
    3438                 :            :         NULL
    3439                 :            : };
    3440                 :            : 
    3441                 :            : static const char *slave_sws_vt1616[] = {
    3442                 :            :         "Front Playback Switch",
    3443                 :            :         "Surround Playback Switch",
    3444                 :            :         "Center Playback Switch",
    3445                 :            :         "LFE Playback Switch",
    3446                 :            :         NULL
    3447                 :            : };
    3448                 :            : 
    3449                 :            : /* find a mixer control element with the given name */
    3450                 :          0 : static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
    3451                 :            :                                                     const char *name)
    3452                 :            : {
    3453                 :            :         struct snd_ctl_elem_id id;
    3454                 :          0 :         memset(&id, 0, sizeof(id));
    3455                 :          0 :         id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
    3456                 :          0 :         strcpy(id.name, name);
    3457                 :          0 :         return snd_ctl_find_id(ac97->bus->card, &id);
    3458                 :            : }
    3459                 :            : 
    3460                 :            : /* create a virtual master control and add slaves */
    3461                 :          0 : static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
    3462                 :            :                                 const unsigned int *tlv, const char **slaves)
    3463                 :            : {
    3464                 :            :         struct snd_kcontrol *kctl;
    3465                 :            :         const char **s;
    3466                 :            :         int err;
    3467                 :            : 
    3468                 :          0 :         kctl = snd_ctl_make_virtual_master(name, tlv);
    3469         [ #  # ]:          0 :         if (!kctl)
    3470                 :            :                 return -ENOMEM;
    3471                 :          0 :         err = snd_ctl_add(ac97->bus->card, kctl);
    3472         [ #  # ]:          0 :         if (err < 0)
    3473                 :            :                 return err;
    3474                 :            : 
    3475         [ #  # ]:          0 :         for (s = slaves; *s; s++) {
    3476                 :            :                 struct snd_kcontrol *sctl;
    3477                 :            : 
    3478                 :          0 :                 sctl = snd_ac97_find_mixer_ctl(ac97, *s);
    3479         [ #  # ]:          0 :                 if (!sctl) {
    3480                 :            :                         snd_printdd("Cannot find slave %s, skipped\n", *s);
    3481                 :          0 :                         continue;
    3482                 :            :                 }
    3483                 :            :                 err = snd_ctl_add_slave(kctl, sctl);
    3484         [ #  # ]:          0 :                 if (err < 0)
    3485                 :            :                         return err;
    3486                 :            :         }
    3487                 :            :         return 0;
    3488                 :            : }
    3489                 :            : 
    3490                 :          0 : static int patch_vt1616_specific(struct snd_ac97 * ac97)
    3491                 :            : {
    3492                 :            :         struct snd_kcontrol *kctl;
    3493                 :            :         int err;
    3494                 :            : 
    3495         [ #  # ]:          0 :         if (snd_ac97_try_bit(ac97, 0x5a, 9))
    3496         [ #  # ]:          0 :                 if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1)) < 0)
    3497                 :            :                         return err;
    3498         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0)
    3499                 :            :                 return err;
    3500                 :            : 
    3501                 :            :         /* There is already a misnamed master switch.  Rename it.  */
    3502                 :          0 :         kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume");
    3503         [ #  # ]:          0 :         if (!kctl)
    3504                 :            :                 return -EINVAL;
    3505                 :            : 
    3506                 :          0 :         snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback");
    3507                 :            : 
    3508                 :          0 :         err = snd_ac97_add_vmaster(ac97, "Master Playback Volume",
    3509                 :            :                                    kctl->tlv.p, slave_vols_vt1616);
    3510         [ #  # ]:          0 :         if (err < 0)
    3511                 :            :                 return err;
    3512                 :            : 
    3513                 :          0 :         err = snd_ac97_add_vmaster(ac97, "Master Playback Switch",
    3514                 :            :                                    NULL, slave_sws_vt1616);
    3515         [ #  # ]:          0 :         if (err < 0)
    3516                 :          0 :                 return err;
    3517                 :            : 
    3518                 :            :         return 0;
    3519                 :            : }
    3520                 :            : 
    3521                 :            : static const struct snd_ac97_build_ops patch_vt1616_ops = {
    3522                 :            :         .build_specific = patch_vt1616_specific
    3523                 :            : };
    3524                 :            : 
    3525                 :          0 : static int patch_vt1616(struct snd_ac97 * ac97)
    3526                 :            : {
    3527                 :          0 :         ac97->build_ops = &patch_vt1616_ops;
    3528                 :          0 :         return 0;
    3529                 :            : }
    3530                 :            : 
    3531                 :            : /*
    3532                 :            :  * VT1617A codec
    3533                 :            :  */
    3534                 :            : 
    3535                 :            : /*
    3536                 :            :  * unfortunately, the vt1617a stashes the twiddlers required for
    3537                 :            :  * noodling the i/o jacks on 2 different regs. that means that we can't
    3538                 :            :  * use the easy way provided by AC97_ENUM_DOUBLE() we have to write
    3539                 :            :  * are own funcs.
    3540                 :            :  *
    3541                 :            :  * NB: this is absolutely and utterly different from the vt1618. dunno
    3542                 :            :  * about the 1616.
    3543                 :            :  */
    3544                 :            : 
    3545                 :            : /* copied from ac97_surround_jack_mode_info() */
    3546                 :          0 : static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol,
    3547                 :            :                                          struct snd_ctl_elem_info *uinfo)
    3548                 :            : {
    3549                 :            :         /* ordering in this list reflects vt1617a docs for Reg 20 and
    3550                 :            :          * 7a and Table 6 that lays out the matrix NB WRT Table6: SM51
    3551                 :            :          * is SM51EN *AND* it's Bit14, not Bit15 so the table is very
    3552                 :            :          * counter-intuitive */ 
    3553                 :            : 
    3554                 :            :         static const char* texts[] = { "LineIn Mic1", "LineIn Mic1 Mic3",
    3555                 :            :                                        "Surr LFE/C Mic3", "LineIn LFE/C Mic3",
    3556                 :            :                                        "LineIn Mic2", "LineIn Mic2 Mic1",
    3557                 :            :                                        "Surr LFE Mic1", "Surr LFE Mic1 Mic2"};
    3558                 :          0 :         return ac97_enum_text_info(kcontrol, uinfo, texts, 8);
    3559                 :            : }
    3560                 :            : 
    3561                 :          0 : static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol,
    3562                 :            :                                         struct snd_ctl_elem_value *ucontrol)
    3563                 :            : {
    3564                 :            :         ushort usSM51, usMS;  
    3565                 :            : 
    3566                 :            :         struct snd_ac97 *pac97;
    3567                 :            :         
    3568                 :          0 :         pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
    3569                 :            : 
    3570                 :            :         /* grab our desired bits, then mash them together in a manner
    3571                 :            :          * consistent with Table 6 on page 17 in the 1617a docs */
    3572                 :            :  
    3573                 :          0 :         usSM51 = snd_ac97_read(pac97, 0x7a) >> 14;
    3574                 :          0 :         usMS   = snd_ac97_read(pac97, 0x20) >> 8;
    3575                 :            :   
    3576                 :          0 :         ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS;
    3577                 :            : 
    3578                 :          0 :         return 0;
    3579                 :            : }
    3580                 :            : 
    3581                 :          0 : static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol,
    3582                 :            :                                         struct snd_ctl_elem_value *ucontrol)
    3583                 :            : {
    3584                 :            :         ushort usSM51, usMS, usReg;  
    3585                 :            : 
    3586                 :            :         struct snd_ac97 *pac97;
    3587                 :            : 
    3588                 :          0 :         pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
    3589                 :            : 
    3590                 :          0 :         usSM51 = ucontrol->value.enumerated.item[0] >> 1;
    3591                 :          0 :         usMS   = ucontrol->value.enumerated.item[0] &  1;
    3592                 :            : 
    3593                 :            :         /* push our values into the register - consider that things will be left
    3594                 :            :          * in a funky state if the write fails */
    3595                 :            : 
    3596                 :          0 :         usReg = snd_ac97_read(pac97, 0x7a);
    3597                 :          0 :         snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14));
    3598                 :          0 :         usReg = snd_ac97_read(pac97, 0x20);
    3599                 :          0 :         snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS   <<  8));
    3600                 :            : 
    3601                 :          0 :         return 0;
    3602                 :            : }
    3603                 :            : 
    3604                 :            : static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = {
    3605                 :            : 
    3606                 :            :         AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0),
    3607                 :            :         /*
    3608                 :            :          * These are used to enable/disable surround sound on motherboards
    3609                 :            :          * that have 3 bidirectional analog jacks
    3610                 :            :          */
    3611                 :            :         {
    3612                 :            :                 .iface         = SNDRV_CTL_ELEM_IFACE_MIXER,
    3613                 :            :                 .name          = "Smart 5.1 Select",
    3614                 :            :                 .info          = snd_ac97_vt1617a_smart51_info,
    3615                 :            :                 .get           = snd_ac97_vt1617a_smart51_get,
    3616                 :            :                 .put           = snd_ac97_vt1617a_smart51_put,
    3617                 :            :         },
    3618                 :            : };
    3619                 :            : 
    3620                 :          0 : static int patch_vt1617a(struct snd_ac97 * ac97)
    3621                 :            : {
    3622                 :            :         int err = 0;
    3623                 :            :         int val;
    3624                 :            : 
    3625                 :            :         /* we choose to not fail out at this point, but we tell the
    3626                 :            :            caller when we return */
    3627                 :            : 
    3628                 :          0 :         err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0],
    3629                 :            :                                    ARRAY_SIZE(snd_ac97_controls_vt1617a));
    3630                 :            : 
    3631                 :            :         /* bring analog power consumption to normal by turning off the
    3632                 :            :          * headphone amplifier, like WinXP driver for EPIA SP
    3633                 :            :          */
    3634                 :            :         /* We need to check the bit before writing it.
    3635                 :            :          * On some (many?) hardwares, setting bit actually clears it!
    3636                 :            :          */
    3637                 :          0 :         val = snd_ac97_read(ac97, 0x5c);
    3638         [ #  # ]:          0 :         if (!(val & 0x20))
    3639                 :          0 :                 snd_ac97_write_cache(ac97, 0x5c, 0x20);
    3640                 :            : 
    3641                 :          0 :         ac97->ext_id |= AC97_EI_SPDIF;       /* force the detection of spdif */
    3642                 :          0 :         ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
    3643                 :          0 :         ac97->build_ops = &patch_vt1616_ops;
    3644                 :            : 
    3645                 :          0 :         return err;
    3646                 :            : }
    3647                 :            : 
    3648                 :            : /* VIA VT1618 8 CHANNEL AC97 CODEC
    3649                 :            :  *
    3650                 :            :  * VIA implements 'Smart 5.1' completely differently on the 1618 than
    3651                 :            :  * it does on the 1617a. awesome! They seem to have sourced this
    3652                 :            :  * particular revision of the technology from somebody else, it's
    3653                 :            :  * called Universal Audio Jack and it shows up on some other folk's chips
    3654                 :            :  * as well.
    3655                 :            :  *
    3656                 :            :  * ordering in this list reflects vt1618 docs for Reg 60h and
    3657                 :            :  * the block diagram, DACs are as follows:
    3658                 :            :  *
    3659                 :            :  *        OUT_O -> Front,
    3660                 :            :  *        OUT_1 -> Surround,
    3661                 :            :  *        OUT_2 -> C/LFE
    3662                 :            :  *
    3663                 :            :  * Unlike the 1617a, each OUT has a consistent set of mappings
    3664                 :            :  * for all bitpatterns other than 00:
    3665                 :            :  *
    3666                 :            :  *        01       Unmixed Output
    3667                 :            :  *        10       Line In
    3668                 :            :  *        11       Mic  In
    3669                 :            :  *
    3670                 :            :  * Special Case of 00:
    3671                 :            :  *
    3672                 :            :  *        OUT_0    Mixed Output
    3673                 :            :  *        OUT_1    Reserved
    3674                 :            :  *        OUT_2    Reserved
    3675                 :            :  *
    3676                 :            :  * I have no idea what the hell Reserved does, but on an MSI
    3677                 :            :  * CN700T, i have to set it to get 5.1 output - YMMV, bad
    3678                 :            :  * shit may happen.
    3679                 :            :  *
    3680                 :            :  * If other chips use Universal Audio Jack, then this code might be applicable
    3681                 :            :  * to them.
    3682                 :            :  */
    3683                 :            : 
    3684                 :            : struct vt1618_uaj_item {
    3685                 :            :         unsigned short mask;
    3686                 :            :         unsigned short shift;
    3687                 :            :         const char *items[4];
    3688                 :            : };
    3689                 :            : 
    3690                 :            : /* This list reflects the vt1618 docs for Vendor Defined Register 0x60. */
    3691                 :            : 
    3692                 :            : static struct vt1618_uaj_item vt1618_uaj[3] = {
    3693                 :            :         {
    3694                 :            :                 /* speaker jack */
    3695                 :            :                 .mask  = 0x03,
    3696                 :            :                 .shift = 0,
    3697                 :            :                 .items = {
    3698                 :            :                         "Speaker Out", "DAC Unmixed Out", "Line In", "Mic In"
    3699                 :            :                 }
    3700                 :            :         },
    3701                 :            :         {
    3702                 :            :                 /* line jack */
    3703                 :            :                 .mask  = 0x0c,
    3704                 :            :                 .shift = 2,
    3705                 :            :                 .items = {
    3706                 :            :                         "Surround Out", "DAC Unmixed Out", "Line In", "Mic In"
    3707                 :            :                 }
    3708                 :            :         },
    3709                 :            :         {
    3710                 :            :                 /* mic jack */
    3711                 :            :                 .mask  = 0x30,
    3712                 :            :                 .shift = 4,
    3713                 :            :                 .items = {
    3714                 :            :                         "Center LFE Out", "DAC Unmixed Out", "Line In", "Mic In"
    3715                 :            :                 },
    3716                 :            :         },
    3717                 :            : };
    3718                 :            : 
    3719                 :          0 : static int snd_ac97_vt1618_UAJ_info(struct snd_kcontrol *kcontrol,
    3720                 :            :                                     struct snd_ctl_elem_info *uinfo)
    3721                 :            : {
    3722                 :          0 :         return ac97_enum_text_info(kcontrol, uinfo,
    3723                 :          0 :                                    vt1618_uaj[kcontrol->private_value].items,
    3724                 :            :                                    4);
    3725                 :            : }
    3726                 :            : 
    3727                 :            : /* All of the vt1618 Universal Audio Jack twiddlers are on
    3728                 :            :  * Vendor Defined Register 0x60, page 0. The bits, and thus
    3729                 :            :  * the mask, are the only thing that changes
    3730                 :            :  */
    3731                 :          0 : static int snd_ac97_vt1618_UAJ_get(struct snd_kcontrol *kcontrol,
    3732                 :            :                                    struct snd_ctl_elem_value *ucontrol)
    3733                 :            : {
    3734                 :            :         unsigned short datpag, uaj;
    3735                 :          0 :         struct snd_ac97 *pac97 = snd_kcontrol_chip(kcontrol);
    3736                 :            : 
    3737                 :          0 :         mutex_lock(&pac97->page_mutex);
    3738                 :            : 
    3739                 :          0 :         datpag = snd_ac97_read(pac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
    3740                 :          0 :         snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, 0);
    3741                 :            : 
    3742                 :          0 :         uaj = snd_ac97_read(pac97, 0x60) &
    3743                 :          0 :                 vt1618_uaj[kcontrol->private_value].mask;
    3744                 :            : 
    3745                 :          0 :         snd_ac97_update_bits(pac97, AC97_INT_PAGING, AC97_PAGE_MASK, datpag);
    3746                 :          0 :         mutex_unlock(&pac97->page_mutex);
    3747                 :            : 
    3748                 :          0 :         ucontrol->value.enumerated.item[0] = uaj >>
    3749                 :          0 :                 vt1618_uaj[kcontrol->private_value].shift;
    3750                 :            : 
    3751                 :          0 :         return 0;
    3752                 :            : }
    3753                 :            : 
    3754                 :          0 : static int snd_ac97_vt1618_UAJ_put(struct snd_kcontrol *kcontrol,
    3755                 :            :                                    struct snd_ctl_elem_value *ucontrol)
    3756                 :            : {
    3757                 :          0 :         return ac97_update_bits_page(snd_kcontrol_chip(kcontrol), 0x60,
    3758                 :          0 :                                      vt1618_uaj[kcontrol->private_value].mask,
    3759                 :          0 :                                      ucontrol->value.enumerated.item[0]<<
    3760                 :          0 :                                      vt1618_uaj[kcontrol->private_value].shift,
    3761                 :            :                                      0);
    3762                 :            : }
    3763                 :            : 
    3764                 :            : /* config aux in jack - not found on 3 jack motherboards or soundcards */
    3765                 :            : 
    3766                 :          0 : static int snd_ac97_vt1618_aux_info(struct snd_kcontrol *kcontrol,
    3767                 :            :                                      struct snd_ctl_elem_info *uinfo)
    3768                 :            : {
    3769                 :            :         static const char *txt_aux[] = {"Aux In", "Back Surr Out"};
    3770                 :            : 
    3771                 :          0 :         return ac97_enum_text_info(kcontrol, uinfo, txt_aux, 2);
    3772                 :            : }
    3773                 :            : 
    3774                 :          0 : static int snd_ac97_vt1618_aux_get(struct snd_kcontrol *kcontrol,
    3775                 :            :                                    struct snd_ctl_elem_value *ucontrol)
    3776                 :            : {
    3777                 :          0 :         ucontrol->value.enumerated.item[0] =
    3778                 :          0 :                 (snd_ac97_read(snd_kcontrol_chip(kcontrol), 0x5c) & 0x0008)>>3;
    3779                 :          0 :         return 0;
    3780                 :            : }
    3781                 :            : 
    3782                 :          0 : static int snd_ac97_vt1618_aux_put(struct snd_kcontrol *kcontrol,
    3783                 :            :                                    struct snd_ctl_elem_value *ucontrol)
    3784                 :            : {
    3785                 :            :         /* toggle surround rear dac power */
    3786                 :            : 
    3787                 :          0 :         snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x5c, 0x0008,
    3788                 :          0 :                              ucontrol->value.enumerated.item[0] << 3);
    3789                 :            : 
    3790                 :            :         /* toggle aux in surround rear out jack */
    3791                 :            : 
    3792                 :          0 :         return snd_ac97_update_bits(snd_kcontrol_chip(kcontrol), 0x76, 0x0008,
    3793                 :          0 :                                     ucontrol->value.enumerated.item[0] << 3);
    3794                 :            : }
    3795                 :            : 
    3796                 :            : static const struct snd_kcontrol_new snd_ac97_controls_vt1618[] = {
    3797                 :            :         AC97_SINGLE("Exchange Center/LFE", 0x5a,  8, 1,     0),
    3798                 :            :         AC97_SINGLE("DC Offset",           0x5a, 10, 1,     0),
    3799                 :            :         AC97_SINGLE("Soft Mute",           0x5c,  0, 1,     1),
    3800                 :            :         AC97_SINGLE("Headphone Amp",       0x5c,  5, 1,     1),
    3801                 :            :         AC97_DOUBLE("Back Surr Volume",    0x5e,  8, 0, 31, 1),
    3802                 :            :         AC97_SINGLE("Back Surr Switch",    0x5e, 15, 1,     1),
    3803                 :            :         {
    3804                 :            :                 .iface         = SNDRV_CTL_ELEM_IFACE_MIXER,
    3805                 :            :                 .name          = "Speaker Jack Mode",
    3806                 :            :                 .info          = snd_ac97_vt1618_UAJ_info,
    3807                 :            :                 .get           = snd_ac97_vt1618_UAJ_get,
    3808                 :            :                 .put           = snd_ac97_vt1618_UAJ_put,
    3809                 :            :                 .private_value = 0
    3810                 :            :         },
    3811                 :            :         {
    3812                 :            :                 .iface         = SNDRV_CTL_ELEM_IFACE_MIXER,
    3813                 :            :                 .name          = "Line Jack Mode",
    3814                 :            :                 .info          = snd_ac97_vt1618_UAJ_info,
    3815                 :            :                 .get           = snd_ac97_vt1618_UAJ_get,
    3816                 :            :                 .put           = snd_ac97_vt1618_UAJ_put,
    3817                 :            :                 .private_value = 1
    3818                 :            :         },
    3819                 :            :         {
    3820                 :            :                 .iface         = SNDRV_CTL_ELEM_IFACE_MIXER,
    3821                 :            :                 .name          = "Mic Jack Mode",
    3822                 :            :                 .info          = snd_ac97_vt1618_UAJ_info,
    3823                 :            :                 .get           = snd_ac97_vt1618_UAJ_get,
    3824                 :            :                 .put           = snd_ac97_vt1618_UAJ_put,
    3825                 :            :                 .private_value = 2
    3826                 :            :         },
    3827                 :            :         {
    3828                 :            :                 .iface         = SNDRV_CTL_ELEM_IFACE_MIXER,
    3829                 :            :                 .name          = "Aux Jack Mode",
    3830                 :            :                 .info          = snd_ac97_vt1618_aux_info,
    3831                 :            :                 .get           = snd_ac97_vt1618_aux_get,
    3832                 :            :                 .put           = snd_ac97_vt1618_aux_put,
    3833                 :            :         }
    3834                 :            : };
    3835                 :            : 
    3836                 :          0 : static int patch_vt1618(struct snd_ac97 *ac97)
    3837                 :            : {
    3838                 :          0 :         return patch_build_controls(ac97, snd_ac97_controls_vt1618,
    3839                 :            :                                     ARRAY_SIZE(snd_ac97_controls_vt1618));
    3840                 :            : }
    3841                 :            : 
    3842                 :            : /*
    3843                 :            :  */
    3844                 :          0 : static void it2646_update_jacks(struct snd_ac97 *ac97)
    3845                 :            : {
    3846                 :            :         /* shared Line-In / Surround Out */
    3847         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, 0x76, 1 << 9,
    3848                 :            :                              is_shared_surrout(ac97) ? (1<<9) : 0);
    3849                 :            :         /* shared Mic / Center/LFE Out */
    3850         [ #  # ]:          0 :         snd_ac97_update_bits(ac97, 0x76, 1 << 10,
    3851                 :            :                              is_shared_clfeout(ac97) ? (1<<10) : 0);
    3852                 :          0 : }
    3853                 :            : 
    3854                 :            : static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {
    3855                 :            :         AC97_SURROUND_JACK_MODE_CTL,
    3856                 :            :         AC97_CHANNEL_MODE_CTL,
    3857                 :            : };
    3858                 :            : 
    3859                 :            : static const struct snd_kcontrol_new snd_ac97_spdif_controls_it2646[] = {
    3860                 :            :         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0x76, 11, 1, 0),
    3861                 :            :         AC97_SINGLE("Analog to IEC958 Output", 0x76, 12, 1, 0),
    3862                 :            :         AC97_SINGLE("IEC958 Input Monitor", 0x76, 13, 1, 0),
    3863                 :            : };
    3864                 :            : 
    3865                 :          0 : static int patch_it2646_specific(struct snd_ac97 * ac97)
    3866                 :            : {
    3867                 :            :         int err;
    3868         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646))) < 0)
    3869                 :            :                 return err;
    3870         [ #  # ]:          0 :         if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646))) < 0)
    3871                 :          0 :                 return err;
    3872                 :            :         return 0;
    3873                 :            : }
    3874                 :            : 
    3875                 :            : static const struct snd_ac97_build_ops patch_it2646_ops = {
    3876                 :            :         .build_specific = patch_it2646_specific,
    3877                 :            :         .update_jacks = it2646_update_jacks
    3878                 :            : };
    3879                 :            : 
    3880                 :          0 : static int patch_it2646(struct snd_ac97 * ac97)
    3881                 :            : {
    3882                 :          0 :         ac97->build_ops = &patch_it2646_ops;
    3883                 :            :         /* full DAC volume */
    3884                 :          0 :         snd_ac97_write_cache(ac97, 0x5E, 0x0808);
    3885                 :          0 :         snd_ac97_write_cache(ac97, 0x7A, 0x0808);
    3886                 :          0 :         return 0;
    3887                 :            : }
    3888                 :            : 
    3889                 :            : /*
    3890                 :            :  * Si3036 codec
    3891                 :            :  */
    3892                 :            : 
    3893                 :            : #define AC97_SI3036_CHIP_ID     0x5a
    3894                 :            : #define AC97_SI3036_LINE_CFG    0x5c
    3895                 :            : 
    3896                 :            : static const struct snd_kcontrol_new snd_ac97_controls_si3036[] = {
    3897                 :            : AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
    3898                 :            : };
    3899                 :            : 
    3900                 :          0 : static int patch_si3036_specific(struct snd_ac97 * ac97)
    3901                 :            : {
    3902                 :            :         int idx, err;
    3903         [ #  # ]:          0 :         for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++)
    3904         [ #  # ]:          0 :                 if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97))) < 0)
    3905                 :            :                         return err;
    3906                 :            :         return 0;
    3907                 :            : }
    3908                 :            : 
    3909                 :            : static const struct snd_ac97_build_ops patch_si3036_ops = {
    3910                 :            :         .build_specific = patch_si3036_specific,
    3911                 :            : };
    3912                 :            : 
    3913                 :          0 : static int mpatch_si3036(struct snd_ac97 * ac97)
    3914                 :            : {
    3915                 :          0 :         ac97->build_ops = &patch_si3036_ops;
    3916                 :          0 :         snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
    3917                 :          0 :         snd_ac97_write_cache(ac97, 0x68, 0);
    3918                 :          0 :         return 0;
    3919                 :            : }
    3920                 :            : 
    3921                 :            : /*
    3922                 :            :  * LM 4550 Codec
    3923                 :            :  *
    3924                 :            :  * We use a static resolution table since LM4550 codec cannot be
    3925                 :            :  * properly autoprobed to determine the resolution via
    3926                 :            :  * check_volume_resolution().
    3927                 :            :  */
    3928                 :            : 
    3929                 :            : static struct snd_ac97_res_table lm4550_restbl[] = {
    3930                 :            :         { AC97_MASTER, 0x1f1f },
    3931                 :            :         { AC97_HEADPHONE, 0x1f1f },
    3932                 :            :         { AC97_MASTER_MONO, 0x001f },
    3933                 :            :         { AC97_PC_BEEP, 0x001f },       /* LSB is ignored */
    3934                 :            :         { AC97_PHONE, 0x001f },
    3935                 :            :         { AC97_MIC, 0x001f },
    3936                 :            :         { AC97_LINE, 0x1f1f },
    3937                 :            :         { AC97_CD, 0x1f1f },
    3938                 :            :         { AC97_VIDEO, 0x1f1f },
    3939                 :            :         { AC97_AUX, 0x1f1f },
    3940                 :            :         { AC97_PCM, 0x1f1f },
    3941                 :            :         { AC97_REC_GAIN, 0x0f0f },
    3942                 :            :         { } /* terminator */
    3943                 :            : };
    3944                 :            : 
    3945                 :          0 : static int patch_lm4550(struct snd_ac97 *ac97)
    3946                 :            : {
    3947                 :          0 :         ac97->res_table = lm4550_restbl;
    3948                 :          0 :         return 0;
    3949                 :            : }
    3950                 :            : 
    3951                 :            : /* 
    3952                 :            :  *  UCB1400 codec (http://www.semiconductors.philips.com/acrobat_download/datasheets/UCB1400-02.pdf)
    3953                 :            :  */
    3954                 :            : static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = {
    3955                 :            : /* enable/disable headphone driver which allows direct connection to
    3956                 :            :    stereo headphone without the use of external DC blocking
    3957                 :            :    capacitors */
    3958                 :            : AC97_SINGLE("Headphone Driver", 0x6a, 6, 1, 0),
    3959                 :            : /* Filter used to compensate the DC offset is added in the ADC to remove idle
    3960                 :            :    tones from the audio band. */
    3961                 :            : AC97_SINGLE("DC Filter", 0x6a, 4, 1, 0),
    3962                 :            : /* Control smart-low-power mode feature. Allows automatic power down
    3963                 :            :    of unused blocks in the ADC analog front end and the PLL. */
    3964                 :            : AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0),
    3965                 :            : };
    3966                 :            : 
    3967                 :          0 : static int patch_ucb1400_specific(struct snd_ac97 * ac97)
    3968                 :            : {
    3969                 :            :         int idx, err;
    3970         [ #  # ]:          0 :         for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++)
    3971         [ #  # ]:          0 :                 if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0)
    3972                 :            :                         return err;
    3973                 :            :         return 0;
    3974                 :            : }
    3975                 :            : 
    3976                 :            : static const struct snd_ac97_build_ops patch_ucb1400_ops = {
    3977                 :            :         .build_specific = patch_ucb1400_specific,
    3978                 :            : };
    3979                 :            : 
    3980                 :          0 : static int patch_ucb1400(struct snd_ac97 * ac97)
    3981                 :            : {
    3982                 :          0 :         ac97->build_ops = &patch_ucb1400_ops;
    3983                 :            :         /* enable headphone driver and smart low power mode by default */
    3984                 :          0 :         snd_ac97_write_cache(ac97, 0x6a, 0x0050);
    3985                 :          0 :         snd_ac97_write_cache(ac97, 0x6c, 0x0030);
    3986                 :          0 :         return 0;
    3987                 :            : }

Generated by: LCOV version 1.9