LCOV - code coverage report
Current view: top level - sound/pci/ac97 - ac97_pcm.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 261 0.0 %
Date: 2014-02-18 Functions: 0 10 0.0 %
Branches: 0 233 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 <linux/delay.h>
      27                 :            : #include <linux/init.h>
      28                 :            : #include <linux/slab.h>
      29                 :            : #include <linux/mutex.h>
      30                 :            : #include <linux/export.h>
      31                 :            : 
      32                 :            : #include <sound/core.h>
      33                 :            : #include <sound/pcm.h>
      34                 :            : #include <sound/control.h>
      35                 :            : #include <sound/ac97_codec.h>
      36                 :            : #include <sound/asoundef.h>
      37                 :            : #include "ac97_id.h"
      38                 :            : #include "ac97_local.h"
      39                 :            : 
      40                 :            : /*
      41                 :            :  *  PCM support
      42                 :            :  */
      43                 :            : 
      44                 :            : static unsigned char rate_reg_tables[2][4][9] = {
      45                 :            : {
      46                 :            :   /* standard rates */
      47                 :            :   {
      48                 :            :         /* 3&4 front, 7&8 rear, 6&9 center/lfe */
      49                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 3 */
      50                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 4 */
      51                 :            :         0xff,                           /* slot 5 */
      52                 :            :         AC97_PCM_LFE_DAC_RATE,          /* slot 6 */
      53                 :            :         AC97_PCM_SURR_DAC_RATE,         /* slot 7 */
      54                 :            :         AC97_PCM_SURR_DAC_RATE,         /* slot 8 */
      55                 :            :         AC97_PCM_LFE_DAC_RATE,          /* slot 9 */
      56                 :            :         0xff,                           /* slot 10 */
      57                 :            :         0xff,                           /* slot 11 */
      58                 :            :   },
      59                 :            :   {
      60                 :            :         /* 7&8 front, 6&9 rear, 10&11 center/lfe */
      61                 :            :         0xff,                           /* slot 3 */
      62                 :            :         0xff,                           /* slot 4 */
      63                 :            :         0xff,                           /* slot 5 */
      64                 :            :         AC97_PCM_SURR_DAC_RATE,         /* slot 6 */
      65                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 7 */
      66                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 8 */
      67                 :            :         AC97_PCM_SURR_DAC_RATE,         /* slot 9 */
      68                 :            :         AC97_PCM_LFE_DAC_RATE,          /* slot 10 */
      69                 :            :         AC97_PCM_LFE_DAC_RATE,          /* slot 11 */
      70                 :            :   },
      71                 :            :   {
      72                 :            :         /* 6&9 front, 10&11 rear, 3&4 center/lfe */
      73                 :            :         AC97_PCM_LFE_DAC_RATE,          /* slot 3 */
      74                 :            :         AC97_PCM_LFE_DAC_RATE,          /* slot 4 */
      75                 :            :         0xff,                           /* slot 5 */
      76                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 6 */
      77                 :            :         0xff,                           /* slot 7 */
      78                 :            :         0xff,                           /* slot 8 */
      79                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 9 */
      80                 :            :         AC97_PCM_SURR_DAC_RATE,         /* slot 10 */
      81                 :            :         AC97_PCM_SURR_DAC_RATE,         /* slot 11 */
      82                 :            :   },
      83                 :            :   {
      84                 :            :         /* 10&11 front, 3&4 rear, 7&8 center/lfe */
      85                 :            :         AC97_PCM_SURR_DAC_RATE,         /* slot 3 */
      86                 :            :         AC97_PCM_SURR_DAC_RATE,         /* slot 4 */
      87                 :            :         0xff,                           /* slot 5 */
      88                 :            :         0xff,                           /* slot 6 */
      89                 :            :         AC97_PCM_LFE_DAC_RATE,          /* slot 7 */
      90                 :            :         AC97_PCM_LFE_DAC_RATE,          /* slot 8 */
      91                 :            :         0xff,                           /* slot 9 */
      92                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 10 */
      93                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 11 */
      94                 :            :   },
      95                 :            : },
      96                 :            : {
      97                 :            :   /* double rates */
      98                 :            :   {
      99                 :            :         /* 3&4 front, 7&8 front (t+1) */
     100                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 3 */
     101                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 4 */
     102                 :            :         0xff,                           /* slot 5 */
     103                 :            :         0xff,                           /* slot 6 */
     104                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 7 */
     105                 :            :         AC97_PCM_FRONT_DAC_RATE,        /* slot 8 */
     106                 :            :         0xff,                           /* slot 9 */
     107                 :            :         0xff,                           /* slot 10 */
     108                 :            :         0xff,                           /* slot 11 */
     109                 :            :   },
     110                 :            :   {
     111                 :            :         /* not specified in the specification */
     112                 :            :         0xff,                           /* slot 3 */
     113                 :            :         0xff,                           /* slot 4 */
     114                 :            :         0xff,                           /* slot 5 */
     115                 :            :         0xff,                           /* slot 6 */
     116                 :            :         0xff,                           /* slot 7 */
     117                 :            :         0xff,                           /* slot 8 */
     118                 :            :         0xff,                           /* slot 9 */
     119                 :            :         0xff,                           /* slot 10 */
     120                 :            :         0xff,                           /* slot 11 */
     121                 :            :   },
     122                 :            :   {
     123                 :            :         0xff,                           /* slot 3 */
     124                 :            :         0xff,                           /* slot 4 */
     125                 :            :         0xff,                           /* slot 5 */
     126                 :            :         0xff,                           /* slot 6 */
     127                 :            :         0xff,                           /* slot 7 */
     128                 :            :         0xff,                           /* slot 8 */
     129                 :            :         0xff,                           /* slot 9 */
     130                 :            :         0xff,                           /* slot 10 */
     131                 :            :         0xff,                           /* slot 11 */
     132                 :            :   },
     133                 :            :   {
     134                 :            :         0xff,                           /* slot 3 */
     135                 :            :         0xff,                           /* slot 4 */
     136                 :            :         0xff,                           /* slot 5 */
     137                 :            :         0xff,                           /* slot 6 */
     138                 :            :         0xff,                           /* slot 7 */
     139                 :            :         0xff,                           /* slot 8 */
     140                 :            :         0xff,                           /* slot 9 */
     141                 :            :         0xff,                           /* slot 10 */
     142                 :            :         0xff,                           /* slot 11 */
     143                 :            :   }
     144                 :            : }};
     145                 :            : 
     146                 :            : /* FIXME: more various mappings for ADC? */
     147                 :            : static unsigned char rate_cregs[9] = {
     148                 :            :         AC97_PCM_LR_ADC_RATE,   /* 3 */
     149                 :            :         AC97_PCM_LR_ADC_RATE,   /* 4 */
     150                 :            :         0xff,                   /* 5 */
     151                 :            :         AC97_PCM_MIC_ADC_RATE,  /* 6 */
     152                 :            :         0xff,                   /* 7 */
     153                 :            :         0xff,                   /* 8 */
     154                 :            :         0xff,                   /* 9 */
     155                 :            :         0xff,                   /* 10 */
     156                 :            :         0xff,                   /* 11 */
     157                 :            : };
     158                 :            : 
     159                 :            : static unsigned char get_slot_reg(struct ac97_pcm *pcm, unsigned short cidx,
     160                 :            :                                   unsigned short slot, int dbl)
     161                 :            : {
     162 [ #  # ][ #  # ]:          0 :         if (slot < 3)
     163                 :            :                 return 0xff;
     164 [ #  # ][ #  # ]:          0 :         if (slot > 11)
     165                 :            :                 return 0xff;
     166 [ #  # ][ #  # ]:          0 :         if (pcm->spdif)
     167                 :            :                 return AC97_SPDIF; /* pseudo register */
     168 [ #  # ][ #  # ]:          0 :         if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK)
     169                 :          0 :                 return rate_reg_tables[dbl][pcm->r[dbl].rate_table[cidx]][slot - 3];
     170                 :            :         else
     171         [ #  # ]:          0 :                 return rate_cregs[slot - 3];
     172                 :            : }
     173                 :            : 
     174                 :          0 : static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate)
     175                 :            : {
     176                 :            :         unsigned short old, bits, reg, mask;
     177                 :            :         unsigned int sbits;
     178                 :            : 
     179         [ #  # ]:          0 :         if (! (ac97->ext_id & AC97_EI_SPDIF))
     180                 :            :                 return -ENODEV;
     181                 :            : 
     182                 :            :         /* TODO: double rate support */
     183         [ #  # ]:          0 :         if (ac97->flags & AC97_CS_SPDIF) {
     184      [ #  #  # ]:          0 :                 switch (rate) {
     185                 :            :                 case 48000: bits = 0; break;
     186                 :          0 :                 case 44100: bits = 1 << AC97_SC_SPSR_SHIFT; break;
     187                 :            :                 default: /* invalid - disable output */
     188                 :          0 :                         snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
     189                 :          0 :                         return -EINVAL;
     190                 :            :                 }
     191                 :            :                 reg = AC97_CSR_SPDIF;
     192                 :            :                 mask = 1 << AC97_SC_SPSR_SHIFT;
     193                 :            :         } else {
     194 [ #  # ][ #  # ]:          0 :                 if (ac97->id == AC97_ID_CM9739 && rate != 48000) {
     195                 :          0 :                         snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
     196                 :          0 :                         return -EINVAL;
     197                 :            :                 }
     198   [ #  #  #  # ]:          0 :                 switch (rate) {
     199                 :            :                 case 44100: bits = AC97_SC_SPSR_44K; break;
     200                 :          0 :                 case 48000: bits = AC97_SC_SPSR_48K; break;
     201                 :          0 :                 case 32000: bits = AC97_SC_SPSR_32K; break;
     202                 :            :                 default: /* invalid - disable output */
     203                 :          0 :                         snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
     204                 :          0 :                         return -EINVAL;
     205                 :            :                 }
     206                 :            :                 reg = AC97_SPDIF;
     207                 :            :                 mask = AC97_SC_SPSR_MASK;
     208                 :            :         }
     209                 :            : 
     210                 :          0 :         mutex_lock(&ac97->reg_mutex);
     211                 :          0 :         old = snd_ac97_read(ac97, reg) & mask;
     212         [ #  # ]:          0 :         if (old != bits) {
     213                 :          0 :                 snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
     214                 :          0 :                 snd_ac97_update_bits_nolock(ac97, reg, mask, bits);
     215                 :            :                 /* update the internal spdif bits */
     216                 :          0 :                 sbits = ac97->spdif_status;
     217         [ #  # ]:          0 :                 if (sbits & IEC958_AES0_PROFESSIONAL) {
     218                 :          0 :                         sbits &= ~IEC958_AES0_PRO_FS;
     219   [ #  #  #  # ]:          0 :                         switch (rate) {
     220                 :          0 :                         case 44100: sbits |= IEC958_AES0_PRO_FS_44100; break;
     221                 :          0 :                         case 48000: sbits |= IEC958_AES0_PRO_FS_48000; break;
     222                 :          0 :                         case 32000: sbits |= IEC958_AES0_PRO_FS_32000; break;
     223                 :            :                         }
     224                 :            :                 } else {
     225                 :          0 :                         sbits &= ~(IEC958_AES3_CON_FS << 24);
     226      [ #  #  # ]:          0 :                         switch (rate) {
     227                 :            :                         case 44100: sbits |= IEC958_AES3_CON_FS_44100<<24; break;
     228                 :          0 :                         case 48000: sbits |= IEC958_AES3_CON_FS_48000<<24; break;
     229                 :          0 :                         case 32000: sbits |= IEC958_AES3_CON_FS_32000<<24; break;
     230                 :            :                         }
     231                 :            :                 }
     232                 :          0 :                 ac97->spdif_status = sbits;
     233                 :            :         }
     234                 :          0 :         snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF);
     235                 :          0 :         mutex_unlock(&ac97->reg_mutex);
     236                 :          0 :         return 0;
     237                 :            : }
     238                 :            : 
     239                 :            : /**
     240                 :            :  * snd_ac97_set_rate - change the rate of the given input/output.
     241                 :            :  * @ac97: the ac97 instance
     242                 :            :  * @reg: the register to change
     243                 :            :  * @rate: the sample rate to set
     244                 :            :  *
     245                 :            :  * Changes the rate of the given input/output on the codec.
     246                 :            :  * If the codec doesn't support VAR, the rate must be 48000 (except
     247                 :            :  * for SPDIF).
     248                 :            :  *
     249                 :            :  * The valid registers are AC97_PMC_MIC_ADC_RATE,
     250                 :            :  * AC97_PCM_FRONT_DAC_RATE, AC97_PCM_LR_ADC_RATE.
     251                 :            :  * AC97_PCM_SURR_DAC_RATE and AC97_PCM_LFE_DAC_RATE are accepted
     252                 :            :  * if the codec supports them.
     253                 :            :  * AC97_SPDIF is accepted as a pseudo register to modify the SPDIF
     254                 :            :  * status bits.
     255                 :            :  *
     256                 :            :  * Return: Zero if successful, or a negative error code on failure.
     257                 :            :  */
     258                 :          0 : int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate)
     259                 :            : {
     260                 :            :         int dbl;
     261                 :            :         unsigned int tmp;
     262                 :            :         
     263                 :          0 :         dbl = rate > 48000;
     264         [ #  # ]:          0 :         if (dbl) {
     265         [ #  # ]:          0 :                 if (!(ac97->flags & AC97_DOUBLE_RATE))
     266                 :            :                         return -EINVAL;
     267         [ #  # ]:          0 :                 if (reg != AC97_PCM_FRONT_DAC_RATE)
     268                 :            :                         return -EINVAL;
     269                 :            :         }
     270                 :            : 
     271                 :            :         snd_ac97_update_power(ac97, reg, 1);
     272   [ #  #  #  #  :          0 :         switch (reg) {
                   #  # ]
     273                 :            :         case AC97_PCM_MIC_ADC_RATE:
     274         [ #  # ]:          0 :                 if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRM) == 0)       /* MIC VRA */
     275         [ #  # ]:          0 :                         if (rate != 48000)
     276                 :            :                                 return -EINVAL;
     277                 :            :                 break;
     278                 :            :         case AC97_PCM_FRONT_DAC_RATE:
     279                 :            :         case AC97_PCM_LR_ADC_RATE:
     280         [ #  # ]:          0 :                 if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRA) == 0)       /* VRA */
     281         [ #  # ]:          0 :                         if (rate != 48000 && rate != 96000)
     282                 :            :                                 return -EINVAL;
     283                 :            :                 break;
     284                 :            :         case AC97_PCM_SURR_DAC_RATE:
     285         [ #  # ]:          0 :                 if (! (ac97->scaps & AC97_SCAP_SURROUND_DAC))
     286                 :            :                         return -EINVAL;
     287                 :            :                 break;
     288                 :            :         case AC97_PCM_LFE_DAC_RATE:
     289         [ #  # ]:          0 :                 if (! (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC))
     290                 :            :                         return -EINVAL;
     291                 :            :                 break;
     292                 :            :         case AC97_SPDIF:
     293                 :            :                 /* special case */
     294                 :          0 :                 return set_spdif_rate(ac97, rate);
     295                 :            :         default:
     296                 :            :                 return -EINVAL;
     297                 :            :         }
     298         [ #  # ]:          0 :         if (dbl)
     299                 :          0 :                 rate /= 2;
     300                 :          0 :         tmp = (rate * ac97->bus->clock) / 48000;
     301         [ #  # ]:          0 :         if (tmp > 65535)
     302                 :            :                 return -EINVAL;
     303 [ #  # ][ #  # ]:          0 :         if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE)
     304         [ #  # ]:          0 :                 snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
     305                 :            :                                      AC97_EA_DRA, dbl ? AC97_EA_DRA : 0);
     306                 :          0 :         snd_ac97_update(ac97, reg, tmp & 0xffff);
     307                 :          0 :         snd_ac97_read(ac97, reg);
     308 [ #  # ][ #  # ]:          0 :         if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE) {
     309                 :            :                 /* Intel controllers require double rate data to be put in
     310                 :            :                  * slots 7+8
     311                 :            :                  */
     312         [ #  # ]:          0 :                 snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE,
     313                 :            :                                      AC97_GP_DRSS_MASK,
     314                 :            :                                      dbl ? AC97_GP_DRSS_78 : 0);
     315                 :          0 :                 snd_ac97_read(ac97, AC97_GENERAL_PURPOSE);
     316                 :            :         }
     317                 :            :         return 0;
     318                 :            : }
     319                 :            : 
     320                 :            : EXPORT_SYMBOL(snd_ac97_set_rate);
     321                 :            : 
     322                 :          0 : static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots)
     323                 :            : {
     324         [ #  # ]:          0 :         if (!ac97_is_audio(ac97))
     325                 :            :                 return 0;
     326 [ #  # ][ #  # ]:          0 :         if (ac97_is_rev22(ac97) || ac97_can_amap(ac97)) {
     327                 :            :                 unsigned short slots = 0;
     328         [ #  # ]:          0 :                 if (ac97_is_rev22(ac97)) {
     329                 :            :                         /* Note: it's simply emulation of AMAP behaviour */
     330                 :            :                         u16 es;
     331                 :          0 :                         es = ac97->regs[AC97_EXTENDED_ID] &= ~AC97_EI_DACS_SLOT_MASK;
     332      [ #  #  # ]:          0 :                         switch (ac97->addr) {
     333                 :            :                         case 1:
     334                 :          0 :                         case 2: es |= (1<<AC97_EI_DACS_SLOT_SHIFT); break;
     335                 :          0 :                         case 3: es |= (2<<AC97_EI_DACS_SLOT_SHIFT); break;
     336                 :            :                         }
     337                 :          0 :                         snd_ac97_write_cache(ac97, AC97_EXTENDED_ID, es);
     338                 :            :                 }
     339   [ #  #  #  # ]:          0 :                 switch (ac97->addr) {
     340                 :            :                 case 0:
     341                 :            :                         slots |= (1<<AC97_SLOT_PCM_LEFT)|(1<<AC97_SLOT_PCM_RIGHT);
     342         [ #  # ]:          0 :                         if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
     343                 :            :                                 slots |= (1<<AC97_SLOT_PCM_SLEFT)|(1<<AC97_SLOT_PCM_SRIGHT);
     344         [ #  # ]:          0 :                         if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
     345                 :          0 :                                 slots |= (1<<AC97_SLOT_PCM_CENTER)|(1<<AC97_SLOT_LFE);
     346         [ #  # ]:          0 :                         if (ac97->ext_id & AC97_EI_SPDIF) {
     347         [ #  # ]:          0 :                                 if (!(ac97->scaps & AC97_SCAP_SURROUND_DAC))
     348                 :          0 :                                         *spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT)|(1<<AC97_SLOT_SPDIF_RIGHT);
     349         [ #  # ]:          0 :                                 else if (!(ac97->scaps & AC97_SCAP_CENTER_LFE_DAC))
     350                 :          0 :                                         *spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT1)|(1<<AC97_SLOT_SPDIF_RIGHT1);
     351                 :            :                                 else
     352                 :          0 :                                         *spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT2)|(1<<AC97_SLOT_SPDIF_RIGHT2);
     353                 :            :                         }
     354                 :          0 :                         *rate_table = 0;
     355                 :          0 :                         break;
     356                 :            :                 case 1:
     357                 :            :                 case 2:
     358                 :            :                         slots |= (1<<AC97_SLOT_PCM_SLEFT)|(1<<AC97_SLOT_PCM_SRIGHT);
     359         [ #  # ]:          0 :                         if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
     360                 :            :                                 slots |= (1<<AC97_SLOT_PCM_CENTER)|(1<<AC97_SLOT_LFE);
     361         [ #  # ]:          0 :                         if (ac97->ext_id & AC97_EI_SPDIF) {
     362         [ #  # ]:          0 :                                 if (!(ac97->scaps & AC97_SCAP_SURROUND_DAC))
     363                 :          0 :                                         *spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT1)|(1<<AC97_SLOT_SPDIF_RIGHT1);
     364                 :            :                                 else
     365                 :          0 :                                         *spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT2)|(1<<AC97_SLOT_SPDIF_RIGHT2);
     366                 :            :                         }
     367                 :          0 :                         *rate_table = 1;
     368                 :          0 :                         break;
     369                 :            :                 case 3:
     370                 :            :                         slots |= (1<<AC97_SLOT_PCM_CENTER)|(1<<AC97_SLOT_LFE);
     371         [ #  # ]:          0 :                         if (ac97->ext_id & AC97_EI_SPDIF)
     372                 :          0 :                                 *spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT2)|(1<<AC97_SLOT_SPDIF_RIGHT2);
     373                 :          0 :                         *rate_table = 2;
     374                 :          0 :                         break;
     375                 :            :                 }
     376                 :          0 :                 return slots;
     377                 :            :         } else {
     378                 :            :                 unsigned short slots;
     379                 :            :                 slots = (1<<AC97_SLOT_PCM_LEFT)|(1<<AC97_SLOT_PCM_RIGHT);
     380         [ #  # ]:          0 :                 if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
     381                 :            :                         slots |= (1<<AC97_SLOT_PCM_SLEFT)|(1<<AC97_SLOT_PCM_SRIGHT);
     382         [ #  # ]:          0 :                 if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
     383                 :          0 :                         slots |= (1<<AC97_SLOT_PCM_CENTER)|(1<<AC97_SLOT_LFE);
     384         [ #  # ]:          0 :                 if (ac97->ext_id & AC97_EI_SPDIF) {
     385         [ #  # ]:          0 :                         if (!(ac97->scaps & AC97_SCAP_SURROUND_DAC))
     386                 :          0 :                                 *spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT)|(1<<AC97_SLOT_SPDIF_RIGHT);
     387         [ #  # ]:          0 :                         else if (!(ac97->scaps & AC97_SCAP_CENTER_LFE_DAC))
     388                 :          0 :                                 *spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT1)|(1<<AC97_SLOT_SPDIF_RIGHT1);
     389                 :            :                         else
     390                 :          0 :                                 *spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT2)|(1<<AC97_SLOT_SPDIF_RIGHT2);
     391                 :            :                 }
     392                 :          0 :                 *rate_table = 0;
     393                 :          0 :                 return slots;
     394                 :            :         }
     395                 :            : }
     396                 :            : 
     397                 :          0 : static unsigned short get_cslots(struct snd_ac97 *ac97)
     398                 :            : {
     399                 :            :         unsigned short slots;
     400                 :            : 
     401         [ #  # ]:          0 :         if (!ac97_is_audio(ac97))
     402                 :            :                 return 0;
     403                 :            :         slots = (1<<AC97_SLOT_PCM_LEFT)|(1<<AC97_SLOT_PCM_RIGHT);
     404                 :            :         slots |= (1<<AC97_SLOT_MIC);
     405                 :            :         return slots;
     406                 :            : }
     407                 :            : 
     408                 :          0 : static unsigned int get_rates(struct ac97_pcm *pcm, unsigned int cidx, unsigned short slots, int dbl)
     409                 :            : {
     410                 :            :         int i, idx;
     411                 :            :         unsigned int rates = ~0;
     412                 :            :         unsigned char reg;
     413                 :            : 
     414         [ #  # ]:          0 :         for (i = 3; i < 12; i++) {
     415         [ #  # ]:          0 :                 if (!(slots & (1 << i)))
     416                 :          0 :                         continue;
     417                 :          0 :                 reg = get_slot_reg(pcm, cidx, i, dbl);
     418                 :            :                 switch (reg) {
     419                 :            :                 case AC97_PCM_FRONT_DAC_RATE:   idx = AC97_RATES_FRONT_DAC; break;
     420                 :            :                 case AC97_PCM_SURR_DAC_RATE:    idx = AC97_RATES_SURR_DAC; break;
     421                 :            :                 case AC97_PCM_LFE_DAC_RATE:     idx = AC97_RATES_LFE_DAC; break;
     422                 :            :                 case AC97_PCM_LR_ADC_RATE:      idx = AC97_RATES_ADC; break;
     423                 :            :                 case AC97_PCM_MIC_ADC_RATE:     idx = AC97_RATES_MIC_ADC; break;
     424                 :            :                 default:                        idx = AC97_RATES_SPDIF; break;
     425                 :            :                 }
     426                 :          0 :                 rates &= pcm->r[dbl].codec[cidx]->rates[idx];
     427                 :            :         }
     428         [ #  # ]:          0 :         if (!dbl)
     429                 :          0 :                 rates &= ~(SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 |
     430                 :            :                            SNDRV_PCM_RATE_96000);
     431                 :          0 :         return rates;
     432                 :            : }
     433                 :            : 
     434                 :            : /**
     435                 :            :  * snd_ac97_pcm_assign - assign AC97 slots to given PCM streams
     436                 :            :  * @bus: the ac97 bus instance
     437                 :            :  * @pcms_count: count of PCMs to be assigned
     438                 :            :  * @pcms: PCMs to be assigned
     439                 :            :  *
     440                 :            :  * It assigns available AC97 slots for given PCMs. If none or only
     441                 :            :  * some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members
     442                 :            :  * are reduced and might be zero.
     443                 :            :  *
     444                 :            :  * Return: Zero if successful, or a negative error code on failure.
     445                 :            :  */
     446                 :          0 : int snd_ac97_pcm_assign(struct snd_ac97_bus *bus,
     447                 :            :                         unsigned short pcms_count,
     448                 :            :                         const struct ac97_pcm *pcms)
     449                 :            : {
     450                 :            :         int i, j, k;
     451                 :            :         const struct ac97_pcm *pcm;
     452                 :            :         struct ac97_pcm *rpcms, *rpcm;
     453                 :            :         unsigned short avail_slots[2][4];
     454                 :            :         unsigned char rate_table[2][4];
     455                 :            :         unsigned short tmp, slots;
     456                 :            :         unsigned short spdif_slots[4];
     457                 :            :         unsigned int rates;
     458                 :            :         struct snd_ac97 *codec;
     459                 :            : 
     460                 :          0 :         rpcms = kcalloc(pcms_count, sizeof(struct ac97_pcm), GFP_KERNEL);
     461         [ #  # ]:          0 :         if (rpcms == NULL)
     462                 :            :                 return -ENOMEM;
     463                 :          0 :         memset(avail_slots, 0, sizeof(avail_slots));
     464                 :          0 :         memset(rate_table, 0, sizeof(rate_table));
     465                 :          0 :         memset(spdif_slots, 0, sizeof(spdif_slots));
     466         [ #  # ]:          0 :         for (i = 0; i < 4; i++) {
     467                 :          0 :                 codec = bus->codec[i];
     468         [ #  # ]:          0 :                 if (!codec)
     469                 :          0 :                         continue;
     470                 :          0 :                 avail_slots[0][i] = get_pslots(codec, &rate_table[0][i], &spdif_slots[i]);
     471                 :          0 :                 avail_slots[1][i] = get_cslots(codec);
     472         [ #  # ]:          0 :                 if (!(codec->scaps & AC97_SCAP_INDEP_SDIN)) {
     473         [ #  # ]:          0 :                         for (j = 0; j < i; j++) {
     474         [ #  # ]:          0 :                                 if (bus->codec[j])
     475                 :          0 :                                         avail_slots[1][i] &= ~avail_slots[1][j];
     476                 :            :                         }
     477                 :            :                 }
     478                 :            :         }
     479                 :            :         /* first step - exclusive devices */
     480         [ #  # ]:          0 :         for (i = 0; i < pcms_count; i++) {
     481                 :          0 :                 pcm = &pcms[i];
     482                 :          0 :                 rpcm = &rpcms[i];
     483                 :            :                 /* low-level driver thinks that it's more clever */
     484         [ #  # ]:          0 :                 if (pcm->copy_flag) {
     485                 :          0 :                         *rpcm = *pcm;
     486                 :          0 :                         continue;
     487                 :            :                 }
     488                 :          0 :                 rpcm->stream = pcm->stream;
     489                 :          0 :                 rpcm->exclusive = pcm->exclusive;
     490                 :          0 :                 rpcm->spdif = pcm->spdif;
     491                 :          0 :                 rpcm->private_value = pcm->private_value;
     492                 :          0 :                 rpcm->bus = bus;
     493                 :          0 :                 rpcm->rates = ~0;
     494                 :          0 :                 slots = pcm->r[0].slots;
     495         [ #  # ]:          0 :                 for (j = 0; j < 4 && slots; j++) {
     496         [ #  # ]:          0 :                         if (!bus->codec[j])
     497                 :          0 :                                 continue;
     498                 :            :                         rates = ~0;
     499         [ #  # ]:          0 :                         if (pcm->spdif && pcm->stream == 0)
     500                 :          0 :                                 tmp = spdif_slots[j];
     501                 :            :                         else
     502                 :          0 :                                 tmp = avail_slots[pcm->stream][j];
     503         [ #  # ]:          0 :                         if (pcm->exclusive) {
     504                 :            :                                 /* exclusive access */
     505                 :          0 :                                 tmp &= slots;
     506         [ #  # ]:          0 :                                 for (k = 0; k < i; k++) {
     507         [ #  # ]:          0 :                                         if (rpcm->stream == rpcms[k].stream)
     508                 :          0 :                                                 tmp &= ~rpcms[k].r[0].rslots[j];
     509                 :            :                                 }
     510                 :            :                         } else {
     511                 :            :                                 /* non-exclusive access */
     512                 :          0 :                                 tmp &= pcm->r[0].slots;
     513                 :            :                         }
     514         [ #  # ]:          0 :                         if (tmp) {
     515                 :          0 :                                 rpcm->r[0].rslots[j] = tmp;
     516                 :          0 :                                 rpcm->r[0].codec[j] = bus->codec[j];
     517                 :          0 :                                 rpcm->r[0].rate_table[j] = rate_table[pcm->stream][j];
     518         [ #  # ]:          0 :                                 if (bus->no_vra)
     519                 :            :                                         rates = SNDRV_PCM_RATE_48000;
     520                 :            :                                 else
     521                 :          0 :                                         rates = get_rates(rpcm, j, tmp, 0);
     522         [ #  # ]:          0 :                                 if (pcm->exclusive)
     523                 :          0 :                                         avail_slots[pcm->stream][j] &= ~tmp;
     524                 :            :                         }
     525                 :          0 :                         slots &= ~tmp;
     526                 :          0 :                         rpcm->r[0].slots |= tmp;
     527                 :          0 :                         rpcm->rates &= rates;
     528                 :            :                 }
     529                 :            :                 /* for double rate, we check the first codec only */
     530 [ #  # ][ #  # ]:          0 :                 if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK &&
     531 [ #  # ][ #  # ]:          0 :                     bus->codec[0] && (bus->codec[0]->flags & AC97_DOUBLE_RATE) &&
     532                 :          0 :                     rate_table[pcm->stream][0] == 0) {
     533                 :            :                         tmp = (1<<AC97_SLOT_PCM_LEFT) | (1<<AC97_SLOT_PCM_RIGHT) |
     534                 :            :                               (1<<AC97_SLOT_PCM_LEFT_0) | (1<<AC97_SLOT_PCM_RIGHT_0);
     535         [ #  # ]:          0 :                         if ((tmp & pcm->r[1].slots) == tmp) {
     536                 :          0 :                                 rpcm->r[1].slots = tmp;
     537                 :          0 :                                 rpcm->r[1].rslots[0] = tmp;
     538                 :          0 :                                 rpcm->r[1].rate_table[0] = 0;
     539                 :          0 :                                 rpcm->r[1].codec[0] = bus->codec[0];
     540         [ #  # ]:          0 :                                 if (pcm->exclusive)
     541                 :          0 :                                         avail_slots[pcm->stream][0] &= ~tmp;
     542         [ #  # ]:          0 :                                 if (bus->no_vra)
     543                 :            :                                         rates = SNDRV_PCM_RATE_96000;
     544                 :            :                                 else
     545                 :          0 :                                         rates = get_rates(rpcm, 0, tmp, 1);
     546                 :          0 :                                 rpcm->rates |= rates;
     547                 :            :                         }
     548                 :            :                 }
     549         [ #  # ]:          0 :                 if (rpcm->rates == ~0)
     550                 :          0 :                         rpcm->rates = 0; /* not used */
     551                 :            :         }
     552                 :          0 :         bus->pcms_count = pcms_count;
     553                 :          0 :         bus->pcms = rpcms;
     554                 :          0 :         return 0;
     555                 :            : }
     556                 :            : 
     557                 :            : EXPORT_SYMBOL(snd_ac97_pcm_assign);
     558                 :            : 
     559                 :            : /**
     560                 :            :  * snd_ac97_pcm_open - opens the given AC97 pcm
     561                 :            :  * @pcm: the ac97 pcm instance
     562                 :            :  * @rate: rate in Hz, if codec does not support VRA, this value must be 48000Hz
     563                 :            :  * @cfg: output stream characteristics
     564                 :            :  * @slots: a subset of allocated slots (snd_ac97_pcm_assign) for this pcm
     565                 :            :  *
     566                 :            :  * It locks the specified slots and sets the given rate to AC97 registers.
     567                 :            :  *
     568                 :            :  * Return: Zero if successful, or a negative error code on failure.
     569                 :            :  */
     570                 :          0 : int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
     571                 :            :                       enum ac97_pcm_cfg cfg, unsigned short slots)
     572                 :            : {
     573                 :            :         struct snd_ac97_bus *bus;
     574                 :            :         int i, cidx, r, ok_flag;
     575                 :          0 :         unsigned int reg_ok[4] = {0,0,0,0};
     576                 :            :         unsigned char reg;
     577                 :            :         int err = 0;
     578                 :            : 
     579                 :          0 :         r = rate > 48000;
     580                 :          0 :         bus = pcm->bus;
     581         [ #  # ]:          0 :         if (cfg == AC97_PCM_CFG_SPDIF) {
     582         [ #  # ]:          0 :                 for (cidx = 0; cidx < 4; cidx++)
     583 [ #  # ][ #  # ]:          0 :                         if (bus->codec[cidx] && (bus->codec[cidx]->ext_id & AC97_EI_SPDIF)) {
     584                 :          0 :                                 err = set_spdif_rate(bus->codec[cidx], rate);
     585         [ #  # ]:          0 :                                 if (err < 0)
     586                 :            :                                         return err;
     587                 :            :                         }
     588                 :            :         }
     589                 :          0 :         spin_lock_irq(&pcm->bus->bus_lock);
     590         [ #  # ]:          0 :         for (i = 3; i < 12; i++) {
     591         [ #  # ]:          0 :                 if (!(slots & (1 << i)))
     592                 :          0 :                         continue;
     593                 :            :                 ok_flag = 0;
     594         [ #  # ]:          0 :                 for (cidx = 0; cidx < 4; cidx++) {
     595         [ #  # ]:          0 :                         if (bus->used_slots[pcm->stream][cidx] & (1 << i)) {
     596                 :          0 :                                 spin_unlock_irq(&pcm->bus->bus_lock);
     597                 :            :                                 err = -EBUSY;
     598                 :          0 :                                 goto error;
     599                 :            :                         }
     600         [ #  # ]:          0 :                         if (pcm->r[r].rslots[cidx] & (1 << i)) {
     601                 :          0 :                                 bus->used_slots[pcm->stream][cidx] |= (1 << i);
     602                 :          0 :                                 ok_flag++;
     603                 :            :                         }
     604                 :            :                 }
     605         [ #  # ]:          0 :                 if (!ok_flag) {
     606                 :          0 :                         spin_unlock_irq(&pcm->bus->bus_lock);
     607                 :          0 :                         snd_printk(KERN_ERR "cannot find configuration for AC97 slot %i\n", i);
     608                 :            :                         err = -EAGAIN;
     609                 :          0 :                         goto error;
     610                 :            :                 }
     611                 :            :         }
     612                 :          0 :         pcm->cur_dbl = r;
     613                 :          0 :         spin_unlock_irq(&pcm->bus->bus_lock);
     614         [ #  # ]:          0 :         for (i = 3; i < 12; i++) {
     615         [ #  # ]:          0 :                 if (!(slots & (1 << i)))
     616                 :          0 :                         continue;
     617         [ #  # ]:          0 :                 for (cidx = 0; cidx < 4; cidx++) {
     618         [ #  # ]:          0 :                         if (pcm->r[r].rslots[cidx] & (1 << i)) {
     619                 :          0 :                                 reg = get_slot_reg(pcm, cidx, i, r);
     620         [ #  # ]:          0 :                                 if (reg == 0xff) {
     621                 :          0 :                                         snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i);
     622                 :          0 :                                         continue;
     623                 :            :                                 }
     624         [ #  # ]:          0 :                                 if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE)))
     625                 :          0 :                                         continue;
     626                 :            :                                 //printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate);
     627                 :          0 :                                 err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate);
     628         [ #  # ]:          0 :                                 if (err < 0)
     629                 :          0 :                                         snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", cidx, reg, rate, err);
     630                 :            :                                 else
     631                 :          0 :                                         reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE));
     632                 :            :                         }
     633                 :            :                 }
     634                 :            :         }
     635                 :          0 :         pcm->aslots = slots;
     636                 :          0 :         return 0;
     637                 :            : 
     638                 :            :  error:
     639                 :          0 :         pcm->aslots = slots;
     640                 :          0 :         snd_ac97_pcm_close(pcm);
     641                 :          0 :         return err;
     642                 :            : }
     643                 :            : 
     644                 :            : EXPORT_SYMBOL(snd_ac97_pcm_open);
     645                 :            : 
     646                 :            : /**
     647                 :            :  * snd_ac97_pcm_close - closes the given AC97 pcm
     648                 :            :  * @pcm: the ac97 pcm instance
     649                 :            :  *
     650                 :            :  * It frees the locked AC97 slots.
     651                 :            :  *
     652                 :            :  * Return: Zero.
     653                 :            :  */
     654                 :          0 : int snd_ac97_pcm_close(struct ac97_pcm *pcm)
     655                 :            : {
     656                 :            :         struct snd_ac97_bus *bus;
     657                 :          0 :         unsigned short slots = pcm->aslots;
     658                 :            :         int i, cidx;
     659                 :            : 
     660                 :            : #ifdef CONFIG_SND_AC97_POWER_SAVE
     661                 :            :         int r = pcm->cur_dbl;
     662                 :            :         for (i = 3; i < 12; i++) {
     663                 :            :                 if (!(slots & (1 << i)))
     664                 :            :                         continue;
     665                 :            :                 for (cidx = 0; cidx < 4; cidx++) {
     666                 :            :                         if (pcm->r[r].rslots[cidx] & (1 << i)) {
     667                 :            :                                 int reg = get_slot_reg(pcm, cidx, i, r);
     668                 :            :                                 snd_ac97_update_power(pcm->r[r].codec[cidx],
     669                 :            :                                                       reg, 0);
     670                 :            :                         }
     671                 :            :                 }
     672                 :            :         }
     673                 :            : #endif
     674                 :            : 
     675                 :          0 :         bus = pcm->bus;
     676                 :            :         spin_lock_irq(&pcm->bus->bus_lock);
     677         [ #  # ]:          0 :         for (i = 3; i < 12; i++) {
     678         [ #  # ]:          0 :                 if (!(slots & (1 << i)))
     679                 :          0 :                         continue;
     680         [ #  # ]:          0 :                 for (cidx = 0; cidx < 4; cidx++)
     681                 :          0 :                         bus->used_slots[pcm->stream][cidx] &= ~(1 << i);
     682                 :            :         }
     683                 :          0 :         pcm->aslots = 0;
     684                 :          0 :         pcm->cur_dbl = 0;
     685                 :          0 :         spin_unlock_irq(&pcm->bus->bus_lock);
     686                 :          0 :         return 0;
     687                 :            : }
     688                 :            : 
     689                 :            : EXPORT_SYMBOL(snd_ac97_pcm_close);
     690                 :            : 
     691                 :          0 : static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params,
     692                 :            :                                           struct snd_pcm_hw_rule *rule)
     693                 :            : {
     694                 :            :         struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
     695         [ #  # ]:          0 :         if (channels->min > 2) {
     696                 :            :                 static const struct snd_interval single_rates = {
     697                 :            :                         .min = 1,
     698                 :            :                         .max = 48000,
     699                 :            :                 };
     700                 :          0 :                 struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
     701                 :          0 :                 return snd_interval_refine(rate, &single_rates);
     702                 :            :         }
     703                 :            :         return 0;
     704                 :            : }
     705                 :            : 
     706                 :          0 : static int double_rate_hw_constraint_channels(struct snd_pcm_hw_params *params,
     707                 :            :                                               struct snd_pcm_hw_rule *rule)
     708                 :            : {
     709                 :            :         struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
     710         [ #  # ]:          0 :         if (rate->min > 48000) {
     711                 :            :                 static const struct snd_interval double_rate_channels = {
     712                 :            :                         .min = 2,
     713                 :            :                         .max = 2,
     714                 :            :                 };
     715                 :          0 :                 struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
     716                 :          0 :                 return snd_interval_refine(channels, &double_rate_channels);
     717                 :            :         }
     718                 :            :         return 0;
     719                 :            : }
     720                 :            : 
     721                 :            : /**
     722                 :            :  * snd_ac97_pcm_double_rate_rules - set double rate constraints
     723                 :            :  * @runtime: the runtime of the ac97 front playback pcm
     724                 :            :  *
     725                 :            :  * Installs the hardware constraint rules to prevent using double rates and
     726                 :            :  * more than two channels at the same time.
     727                 :            :  *
     728                 :            :  * Return: Zero if successful, or a negative error code on failure.
     729                 :            :  */
     730                 :          0 : int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime)
     731                 :            : {
     732                 :            :         int err;
     733                 :            : 
     734                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
     735                 :            :                                   double_rate_hw_constraint_rate, NULL,
     736                 :            :                                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
     737         [ #  # ]:          0 :         if (err < 0)
     738                 :            :                 return err;
     739                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
     740                 :            :                                   double_rate_hw_constraint_channels, NULL,
     741                 :            :                                   SNDRV_PCM_HW_PARAM_RATE, -1);
     742                 :          0 :         return err;
     743                 :            : }
     744                 :            : 
     745                 :            : EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules);

Generated by: LCOV version 1.9