root/sound/pci/ac97/ac97_pcm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_slot_reg
  2. set_spdif_rate
  3. snd_ac97_set_rate
  4. get_pslots
  5. get_cslots
  6. get_rates
  7. snd_ac97_pcm_assign
  8. snd_ac97_pcm_open
  9. snd_ac97_pcm_close
  10. double_rate_hw_constraint_rate
  11. double_rate_hw_constraint_channels
  12. snd_ac97_pcm_double_rate_rules

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

/* [<][>][^][v][top][bottom][index][help] */