LCOV - code coverage report
Current view: top level - sound/core - pcm_native.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 16 1289 1.2 %
Date: 2014-02-18 Functions: 1 107 0.9 %
Branches: 1 960 0.1 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  Digital Audio (PCM) abstract layer
       3                 :            :  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
       4                 :            :  *
       5                 :            :  *
       6                 :            :  *   This program is free software; you can redistribute it and/or modify
       7                 :            :  *   it under the terms of the GNU General Public License as published by
       8                 :            :  *   the Free Software Foundation; either version 2 of the License, or
       9                 :            :  *   (at your option) any later version.
      10                 :            :  *
      11                 :            :  *   This program is distributed in the hope that it will be useful,
      12                 :            :  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :            :  *   GNU General Public License for more details.
      15                 :            :  *
      16                 :            :  *   You should have received a copy of the GNU General Public License
      17                 :            :  *   along with this program; if not, write to the Free Software
      18                 :            :  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
      19                 :            :  *
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <linux/mm.h>
      23                 :            : #include <linux/module.h>
      24                 :            : #include <linux/file.h>
      25                 :            : #include <linux/slab.h>
      26                 :            : #include <linux/time.h>
      27                 :            : #include <linux/pm_qos.h>
      28                 :            : #include <linux/aio.h>
      29                 :            : #include <linux/dma-mapping.h>
      30                 :            : #include <sound/core.h>
      31                 :            : #include <sound/control.h>
      32                 :            : #include <sound/info.h>
      33                 :            : #include <sound/pcm.h>
      34                 :            : #include <sound/pcm_params.h>
      35                 :            : #include <sound/timer.h>
      36                 :            : #include <sound/minors.h>
      37                 :            : #include <asm/io.h>
      38                 :            : #if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
      39                 :            : #include <dma-coherence.h>
      40                 :            : #endif
      41                 :            : 
      42                 :            : /*
      43                 :            :  *  Compatibility
      44                 :            :  */
      45                 :            : 
      46                 :            : struct snd_pcm_hw_params_old {
      47                 :            :         unsigned int flags;
      48                 :            :         unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
      49                 :            :                            SNDRV_PCM_HW_PARAM_ACCESS + 1];
      50                 :            :         struct snd_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
      51                 :            :                                         SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
      52                 :            :         unsigned int rmask;
      53                 :            :         unsigned int cmask;
      54                 :            :         unsigned int info;
      55                 :            :         unsigned int msbits;
      56                 :            :         unsigned int rate_num;
      57                 :            :         unsigned int rate_den;
      58                 :            :         snd_pcm_uframes_t fifo_size;
      59                 :            :         unsigned char reserved[64];
      60                 :            : };
      61                 :            : 
      62                 :            : #ifdef CONFIG_SND_SUPPORT_OLD_API
      63                 :            : #define SNDRV_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct snd_pcm_hw_params_old)
      64                 :            : #define SNDRV_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct snd_pcm_hw_params_old)
      65                 :            : 
      66                 :            : static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
      67                 :            :                                       struct snd_pcm_hw_params_old __user * _oparams);
      68                 :            : static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
      69                 :            :                                       struct snd_pcm_hw_params_old __user * _oparams);
      70                 :            : #endif
      71                 :            : static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
      72                 :            : 
      73                 :            : /*
      74                 :            :  *
      75                 :            :  */
      76                 :            : 
      77                 :            : DEFINE_RWLOCK(snd_pcm_link_rwlock);
      78                 :            : EXPORT_SYMBOL(snd_pcm_link_rwlock);
      79                 :            : 
      80                 :            : static DECLARE_RWSEM(snd_pcm_link_rwsem);
      81                 :            : 
      82                 :            : static inline mm_segment_t snd_enter_user(void)
      83                 :            : {
      84                 :          0 :         mm_segment_t fs = get_fs();
      85                 :            :         set_fs(get_ds());
      86                 :            :         return fs;
      87                 :            : }
      88                 :            : 
      89                 :            : static inline void snd_leave_user(mm_segment_t fs)
      90                 :            : {
      91                 :            :         set_fs(fs);
      92                 :            : }
      93                 :            : 
      94                 :            : 
      95                 :            : 
      96                 :          0 : int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
      97                 :            : {
      98                 :            :         struct snd_pcm_runtime *runtime;
      99                 :          4 :         struct snd_pcm *pcm = substream->pcm;
     100                 :          4 :         struct snd_pcm_str *pstr = substream->pstr;
     101                 :            : 
     102                 :          4 :         memset(info, 0, sizeof(*info));
     103                 :          4 :         info->card = pcm->card->number;
     104                 :          4 :         info->device = pcm->device;
     105                 :          4 :         info->stream = substream->stream;
     106                 :          4 :         info->subdevice = substream->number;
     107                 :          4 :         strlcpy(info->id, pcm->id, sizeof(info->id));
     108                 :          4 :         strlcpy(info->name, pcm->name, sizeof(info->name));
     109                 :          4 :         info->dev_class = pcm->dev_class;
     110                 :          4 :         info->dev_subclass = pcm->dev_subclass;
     111                 :          4 :         info->subdevices_count = pstr->substream_count;
     112                 :          4 :         info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
     113                 :          4 :         strlcpy(info->subname, substream->name, sizeof(info->subname));
     114                 :          4 :         runtime = substream->runtime;
     115                 :            :         /* AB: FIXME!!! This is definitely nonsense */
     116         [ -  + ]:          4 :         if (runtime) {
     117                 :          0 :                 info->sync = runtime->sync;
     118                 :          0 :                 substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
     119                 :            :         }
     120                 :          0 :         return 0;
     121                 :            : }
     122                 :            : 
     123                 :          0 : int snd_pcm_info_user(struct snd_pcm_substream *substream,
     124                 :            :                       struct snd_pcm_info __user * _info)
     125                 :            : {
     126                 :            :         struct snd_pcm_info *info;
     127                 :            :         int err;
     128                 :            : 
     129                 :            :         info = kmalloc(sizeof(*info), GFP_KERNEL);
     130         [ #  # ]:          0 :         if (! info)
     131                 :            :                 return -ENOMEM;
     132                 :          0 :         err = snd_pcm_info(substream, info);
     133         [ #  # ]:          0 :         if (err >= 0) {
     134         [ #  # ]:          0 :                 if (copy_to_user(_info, info, sizeof(*info)))
     135                 :            :                         err = -EFAULT;
     136                 :            :         }
     137                 :          0 :         kfree(info);
     138                 :          0 :         return err;
     139                 :            : }
     140                 :            : 
     141                 :            : #undef RULES_DEBUG
     142                 :            : 
     143                 :            : #ifdef RULES_DEBUG
     144                 :            : #define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v
     145                 :            : static const char * const snd_pcm_hw_param_names[] = {
     146                 :            :         HW_PARAM(ACCESS),
     147                 :            :         HW_PARAM(FORMAT),
     148                 :            :         HW_PARAM(SUBFORMAT),
     149                 :            :         HW_PARAM(SAMPLE_BITS),
     150                 :            :         HW_PARAM(FRAME_BITS),
     151                 :            :         HW_PARAM(CHANNELS),
     152                 :            :         HW_PARAM(RATE),
     153                 :            :         HW_PARAM(PERIOD_TIME),
     154                 :            :         HW_PARAM(PERIOD_SIZE),
     155                 :            :         HW_PARAM(PERIOD_BYTES),
     156                 :            :         HW_PARAM(PERIODS),
     157                 :            :         HW_PARAM(BUFFER_TIME),
     158                 :            :         HW_PARAM(BUFFER_SIZE),
     159                 :            :         HW_PARAM(BUFFER_BYTES),
     160                 :            :         HW_PARAM(TICK_TIME),
     161                 :            : };
     162                 :            : #endif
     163                 :            : 
     164                 :          0 : int snd_pcm_hw_refine(struct snd_pcm_substream *substream, 
     165                 :            :                       struct snd_pcm_hw_params *params)
     166                 :            : {
     167                 :            :         unsigned int k;
     168                 :            :         struct snd_pcm_hardware *hw;
     169                 :          0 :         struct snd_interval *i = NULL;
     170                 :            :         struct snd_mask *m = NULL;
     171                 :          0 :         struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints;
     172                 :          0 :         unsigned int rstamps[constrs->rules_num];
     173                 :            :         unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
     174                 :            :         unsigned int stamp = 2;
     175                 :            :         int changed, again;
     176                 :            : 
     177                 :          0 :         params->info = 0;
     178                 :          0 :         params->fifo_size = 0;
     179         [ #  # ]:          0 :         if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS))
     180                 :          0 :                 params->msbits = 0;
     181         [ #  # ]:          0 :         if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) {
     182                 :          0 :                 params->rate_num = 0;
     183                 :          0 :                 params->rate_den = 0;
     184                 :            :         }
     185                 :            : 
     186         [ #  # ]:          0 :         for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
     187                 :          0 :                 m = hw_param_mask(params, k);
     188         [ #  # ]:          0 :                 if (snd_mask_empty(m))
     189                 :            :                         return -EINVAL;
     190         [ #  # ]:          0 :                 if (!(params->rmask & (1 << k)))
     191                 :          0 :                         continue;
     192                 :            : #ifdef RULES_DEBUG
     193                 :            :                 printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
     194                 :            :                 printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
     195                 :            : #endif
     196                 :          0 :                 changed = snd_mask_refine(m, constrs_mask(constrs, k));
     197                 :            : #ifdef RULES_DEBUG
     198                 :            :                 printk("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
     199                 :            : #endif
     200         [ #  # ]:          0 :                 if (changed)
     201                 :          0 :                         params->cmask |= 1 << k;
     202         [ #  # ]:          0 :                 if (changed < 0)
     203                 :            :                         return changed;
     204                 :            :         }
     205                 :            : 
     206         [ #  # ]:          0 :         for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
     207                 :          0 :                 i = hw_param_interval(params, k);
     208         [ #  # ]:          0 :                 if (snd_interval_empty(i))
     209                 :            :                         return -EINVAL;
     210         [ #  # ]:          0 :                 if (!(params->rmask & (1 << k)))
     211                 :          0 :                         continue;
     212                 :            : #ifdef RULES_DEBUG
     213                 :            :                 printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
     214                 :            :                 if (i->empty)
     215                 :            :                         printk("empty");
     216                 :            :                 else
     217                 :            :                         printk("%c%u %u%c", 
     218                 :            :                                i->openmin ? '(' : '[', i->min,
     219                 :            :                                i->max, i->openmax ? ')' : ']');
     220                 :            :                 printk(" -> ");
     221                 :            : #endif
     222                 :          0 :                 changed = snd_interval_refine(i, constrs_interval(constrs, k));
     223                 :            : #ifdef RULES_DEBUG
     224                 :            :                 if (i->empty)
     225                 :            :                         printk("empty\n");
     226                 :            :                 else 
     227                 :            :                         printk("%c%u %u%c\n", 
     228                 :            :                                i->openmin ? '(' : '[', i->min,
     229                 :            :                                i->max, i->openmax ? ')' : ']');
     230                 :            : #endif
     231         [ #  # ]:          0 :                 if (changed)
     232                 :          0 :                         params->cmask |= 1 << k;
     233         [ #  # ]:          0 :                 if (changed < 0)
     234                 :            :                         return changed;
     235                 :            :         }
     236                 :            : 
     237         [ #  # ]:          0 :         for (k = 0; k < constrs->rules_num; k++)
     238                 :          0 :                 rstamps[k] = 0;
     239         [ #  # ]:          0 :         for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) 
     240                 :          0 :                 vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
     241                 :            :         do {
     242                 :            :                 again = 0;
     243         [ #  # ]:          0 :                 for (k = 0; k < constrs->rules_num; k++) {
     244                 :          0 :                         struct snd_pcm_hw_rule *r = &constrs->rules[k];
     245                 :            :                         unsigned int d;
     246                 :            :                         int doit = 0;
     247 [ #  # ][ #  # ]:          0 :                         if (r->cond && !(r->cond & params->flags))
     248                 :          0 :                                 continue;
     249         [ #  # ]:          0 :                         for (d = 0; r->deps[d] >= 0; d++) {
     250         [ #  # ]:          0 :                                 if (vstamps[r->deps[d]] > rstamps[k]) {
     251                 :            :                                         doit = 1;
     252                 :            :                                         break;
     253                 :            :                                 }
     254                 :            :                         }
     255         [ #  # ]:          0 :                         if (!doit)
     256                 :          0 :                                 continue;
     257                 :            : #ifdef RULES_DEBUG
     258                 :            :                         printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func);
     259                 :            :                         if (r->var >= 0) {
     260                 :            :                                 printk("%s = ", snd_pcm_hw_param_names[r->var]);
     261                 :            :                                 if (hw_is_mask(r->var)) {
     262                 :            :                                         m = hw_param_mask(params, r->var);
     263                 :            :                                         printk("%x", *m->bits);
     264                 :            :                                 } else {
     265                 :            :                                         i = hw_param_interval(params, r->var);
     266                 :            :                                         if (i->empty)
     267                 :            :                                                 printk("empty");
     268                 :            :                                         else
     269                 :            :                                                 printk("%c%u %u%c", 
     270                 :            :                                                        i->openmin ? '(' : '[', i->min,
     271                 :            :                                                        i->max, i->openmax ? ')' : ']');
     272                 :            :                                 }
     273                 :            :                         }
     274                 :            : #endif
     275                 :          0 :                         changed = r->func(params, r);
     276                 :            : #ifdef RULES_DEBUG
     277                 :            :                         if (r->var >= 0) {
     278                 :            :                                 printk(" -> ");
     279                 :            :                                 if (hw_is_mask(r->var))
     280                 :            :                                         printk("%x", *m->bits);
     281                 :            :                                 else {
     282                 :            :                                         if (i->empty)
     283                 :            :                                                 printk("empty");
     284                 :            :                                         else
     285                 :            :                                                 printk("%c%u %u%c", 
     286                 :            :                                                        i->openmin ? '(' : '[', i->min,
     287                 :            :                                                        i->max, i->openmax ? ')' : ']');
     288                 :            :                                 }
     289                 :            :                         }
     290                 :            :                         printk("\n");
     291                 :            : #endif
     292                 :          0 :                         rstamps[k] = stamp;
     293 [ #  # ][ #  # ]:          0 :                         if (changed && r->var >= 0) {
     294                 :          0 :                                 params->cmask |= (1 << r->var);
     295                 :          0 :                                 vstamps[r->var] = stamp;
     296                 :            :                                 again = 1;
     297                 :            :                         }
     298         [ #  # ]:          0 :                         if (changed < 0)
     299                 :            :                                 return changed;
     300                 :          0 :                         stamp++;
     301                 :            :                 }
     302         [ #  # ]:          0 :         } while (again);
     303         [ #  # ]:          0 :         if (!params->msbits) {
     304                 :            :                 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
     305         [ #  # ]:          0 :                 if (snd_interval_single(i))
     306                 :          0 :                         params->msbits = snd_interval_value(i);
     307                 :            :         }
     308                 :            : 
     309         [ #  # ]:          0 :         if (!params->rate_den) {
     310                 :            :                 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
     311         [ #  # ]:          0 :                 if (snd_interval_single(i)) {
     312                 :          0 :                         params->rate_num = snd_interval_value(i);
     313                 :          0 :                         params->rate_den = 1;
     314                 :            :                 }
     315                 :            :         }
     316                 :            : 
     317                 :          0 :         hw = &substream->runtime->hw;
     318         [ #  # ]:          0 :         if (!params->info)
     319                 :          0 :                 params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES;
     320         [ #  # ]:          0 :         if (!params->fifo_size) {
     321                 :            :                 m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
     322                 :            :                 i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
     323 [ #  # ][ #  # ]:          0 :                 if (snd_mask_min(m) == snd_mask_max(m) &&
     324                 :            :                     snd_interval_min(i) == snd_interval_max(i)) {
     325                 :          0 :                         changed = substream->ops->ioctl(substream,
     326                 :            :                                         SNDRV_PCM_IOCTL1_FIFO_SIZE, params);
     327         [ #  # ]:          0 :                         if (changed < 0)
     328                 :            :                                 return changed;
     329                 :            :                 }
     330                 :            :         }
     331                 :          0 :         params->rmask = 0;
     332                 :          0 :         return 0;
     333                 :            : }
     334                 :            : 
     335                 :            : EXPORT_SYMBOL(snd_pcm_hw_refine);
     336                 :            : 
     337                 :          0 : static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
     338                 :            :                                   struct snd_pcm_hw_params __user * _params)
     339                 :            : {
     340                 :            :         struct snd_pcm_hw_params *params;
     341                 :            :         int err;
     342                 :            : 
     343                 :          0 :         params = memdup_user(_params, sizeof(*params));
     344         [ #  # ]:          0 :         if (IS_ERR(params))
     345                 :          0 :                 return PTR_ERR(params);
     346                 :            : 
     347                 :          0 :         err = snd_pcm_hw_refine(substream, params);
     348         [ #  # ]:          0 :         if (copy_to_user(_params, params, sizeof(*params))) {
     349         [ #  # ]:          0 :                 if (!err)
     350                 :            :                         err = -EFAULT;
     351                 :            :         }
     352                 :            : 
     353                 :          0 :         kfree(params);
     354                 :          0 :         return err;
     355                 :            : }
     356                 :            : 
     357                 :            : static int period_to_usecs(struct snd_pcm_runtime *runtime)
     358                 :            : {
     359                 :            :         int usecs;
     360                 :            : 
     361         [ #  # ]:          0 :         if (! runtime->rate)
     362                 :            :                 return -1; /* invalid */
     363                 :            : 
     364                 :            :         /* take 75% of period time as the deadline */
     365                 :          0 :         usecs = (750000 / runtime->rate) * runtime->period_size;
     366                 :          0 :         usecs += ((750000 % runtime->rate) * runtime->period_size) /
     367                 :            :                 runtime->rate;
     368                 :            : 
     369                 :            :         return usecs;
     370                 :            : }
     371                 :            : 
     372                 :          0 : static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
     373                 :            : {
     374                 :            :         snd_pcm_stream_lock_irq(substream);
     375         [ #  # ]:          0 :         if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
     376                 :          0 :                 substream->runtime->status->state = state;
     377                 :            :         snd_pcm_stream_unlock_irq(substream);
     378                 :          0 : }
     379                 :            : 
     380                 :          0 : static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
     381                 :            :                              struct snd_pcm_hw_params *params)
     382                 :            : {
     383                 :          0 :         struct snd_pcm_runtime *runtime;
     384                 :            :         int err, usecs;
     385                 :            :         unsigned int bits;
     386                 :            :         snd_pcm_uframes_t frames;
     387                 :            : 
     388 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
     389                 :            :                 return -ENXIO;
     390                 :          0 :         runtime = substream->runtime;
     391                 :            :         snd_pcm_stream_lock_irq(substream);
     392         [ #  # ]:          0 :         switch (runtime->status->state) {
     393                 :            :         case SNDRV_PCM_STATE_OPEN:
     394                 :            :         case SNDRV_PCM_STATE_SETUP:
     395                 :            :         case SNDRV_PCM_STATE_PREPARED:
     396                 :            :                 break;
     397                 :            :         default:
     398                 :            :                 snd_pcm_stream_unlock_irq(substream);
     399                 :          0 :                 return -EBADFD;
     400                 :            :         }
     401                 :            :         snd_pcm_stream_unlock_irq(substream);
     402                 :            : #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
     403                 :            :         if (!substream->oss.oss)
     404                 :            : #endif
     405         [ #  # ]:          0 :                 if (atomic_read(&substream->mmap_count))
     406                 :            :                         return -EBADFD;
     407                 :            : 
     408                 :          0 :         params->rmask = ~0U;
     409                 :          0 :         err = snd_pcm_hw_refine(substream, params);
     410         [ #  # ]:          0 :         if (err < 0)
     411                 :            :                 goto _error;
     412                 :            : 
     413                 :          0 :         err = snd_pcm_hw_params_choose(substream, params);
     414         [ #  # ]:          0 :         if (err < 0)
     415                 :            :                 goto _error;
     416                 :            : 
     417         [ #  # ]:          0 :         if (substream->ops->hw_params != NULL) {
     418                 :          0 :                 err = substream->ops->hw_params(substream, params);
     419         [ #  # ]:          0 :                 if (err < 0)
     420                 :            :                         goto _error;
     421                 :            :         }
     422                 :            : 
     423                 :          0 :         runtime->access = params_access(params);
     424                 :          0 :         runtime->format = params_format(params);
     425                 :          0 :         runtime->subformat = params_subformat(params);
     426                 :          0 :         runtime->channels = params_channels(params);
     427                 :          0 :         runtime->rate = params_rate(params);
     428                 :          0 :         runtime->period_size = params_period_size(params);
     429                 :          0 :         runtime->periods = params_periods(params);
     430                 :          0 :         runtime->buffer_size = params_buffer_size(params);
     431                 :          0 :         runtime->info = params->info;
     432                 :          0 :         runtime->rate_num = params->rate_num;
     433                 :          0 :         runtime->rate_den = params->rate_den;
     434                 :          0 :         runtime->no_period_wakeup =
     435 [ #  # ][ #  # ]:          0 :                         (params->info & SNDRV_PCM_INFO_NO_PERIOD_WAKEUP) &&
     436                 :          0 :                         (params->flags & SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP);
     437                 :            : 
     438                 :          0 :         bits = snd_pcm_format_physical_width(runtime->format);
     439                 :          0 :         runtime->sample_bits = bits;
     440                 :          0 :         bits *= runtime->channels;
     441                 :          0 :         runtime->frame_bits = bits;
     442                 :            :         frames = 1;
     443         [ #  # ]:          0 :         while (bits % 8 != 0) {
     444                 :          0 :                 bits *= 2;
     445                 :          0 :                 frames *= 2;
     446                 :            :         }
     447                 :          0 :         runtime->byte_align = bits / 8;
     448                 :          0 :         runtime->min_align = frames;
     449                 :            : 
     450                 :            :         /* Default sw params */
     451                 :          0 :         runtime->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
     452                 :          0 :         runtime->period_step = 1;
     453                 :          0 :         runtime->control->avail_min = runtime->period_size;
     454                 :          0 :         runtime->start_threshold = 1;
     455                 :          0 :         runtime->stop_threshold = runtime->buffer_size;
     456                 :          0 :         runtime->silence_threshold = 0;
     457                 :          0 :         runtime->silence_size = 0;
     458                 :          0 :         runtime->boundary = runtime->buffer_size;
     459         [ #  # ]:          0 :         while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
     460                 :          0 :                 runtime->boundary *= 2;
     461                 :            : 
     462                 :          0 :         snd_pcm_timer_resolution_change(substream);
     463                 :          0 :         snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
     464                 :            : 
     465         [ #  # ]:          0 :         if (pm_qos_request_active(&substream->latency_pm_qos_req))
     466                 :          0 :                 pm_qos_remove_request(&substream->latency_pm_qos_req);
     467         [ #  # ]:          0 :         if ((usecs = period_to_usecs(runtime)) >= 0)
     468                 :          0 :                 pm_qos_add_request(&substream->latency_pm_qos_req,
     469                 :            :                                    PM_QOS_CPU_DMA_LATENCY, usecs);
     470                 :            :         return 0;
     471                 :            :  _error:
     472                 :            :         /* hardware might be unusable from this time,
     473                 :            :            so we force application to retry to set
     474                 :            :            the correct hardware parameter settings */
     475                 :          0 :         snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
     476         [ #  # ]:          0 :         if (substream->ops->hw_free != NULL)
     477                 :          0 :                 substream->ops->hw_free(substream);
     478                 :          0 :         return err;
     479                 :            : }
     480                 :            : 
     481                 :          0 : static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
     482                 :            :                                   struct snd_pcm_hw_params __user * _params)
     483                 :            : {
     484                 :            :         struct snd_pcm_hw_params *params;
     485                 :            :         int err;
     486                 :            : 
     487                 :          0 :         params = memdup_user(_params, sizeof(*params));
     488         [ #  # ]:          0 :         if (IS_ERR(params))
     489                 :          0 :                 return PTR_ERR(params);
     490                 :            : 
     491                 :          0 :         err = snd_pcm_hw_params(substream, params);
     492         [ #  # ]:          0 :         if (copy_to_user(_params, params, sizeof(*params))) {
     493         [ #  # ]:          0 :                 if (!err)
     494                 :            :                         err = -EFAULT;
     495                 :            :         }
     496                 :            : 
     497                 :          0 :         kfree(params);
     498                 :          0 :         return err;
     499                 :            : }
     500                 :            : 
     501                 :          0 : static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
     502                 :            : {
     503                 :            :         struct snd_pcm_runtime *runtime;
     504                 :            :         int result = 0;
     505                 :            : 
     506 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
     507                 :            :                 return -ENXIO;
     508                 :          0 :         runtime = substream->runtime;
     509                 :            :         snd_pcm_stream_lock_irq(substream);
     510         [ #  # ]:          0 :         switch (runtime->status->state) {
     511                 :            :         case SNDRV_PCM_STATE_SETUP:
     512                 :            :         case SNDRV_PCM_STATE_PREPARED:
     513                 :            :                 break;
     514                 :            :         default:
     515                 :            :                 snd_pcm_stream_unlock_irq(substream);
     516                 :          0 :                 return -EBADFD;
     517                 :            :         }
     518                 :            :         snd_pcm_stream_unlock_irq(substream);
     519         [ #  # ]:          0 :         if (atomic_read(&substream->mmap_count))
     520                 :            :                 return -EBADFD;
     521         [ #  # ]:          0 :         if (substream->ops->hw_free)
     522                 :          0 :                 result = substream->ops->hw_free(substream);
     523                 :          0 :         snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
     524                 :          0 :         pm_qos_remove_request(&substream->latency_pm_qos_req);
     525                 :          0 :         return result;
     526                 :            : }
     527                 :            : 
     528                 :          0 : static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
     529                 :            :                              struct snd_pcm_sw_params *params)
     530                 :            : {
     531                 :            :         struct snd_pcm_runtime *runtime;
     532                 :            :         int err;
     533                 :            : 
     534 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
     535                 :            :                 return -ENXIO;
     536                 :          0 :         runtime = substream->runtime;
     537                 :            :         snd_pcm_stream_lock_irq(substream);
     538         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
     539                 :            :                 snd_pcm_stream_unlock_irq(substream);
     540                 :          0 :                 return -EBADFD;
     541                 :            :         }
     542                 :            :         snd_pcm_stream_unlock_irq(substream);
     543                 :            : 
     544         [ #  # ]:          0 :         if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
     545                 :            :                 return -EINVAL;
     546         [ #  # ]:          0 :         if (params->avail_min == 0)
     547                 :            :                 return -EINVAL;
     548         [ #  # ]:          0 :         if (params->silence_size >= runtime->boundary) {
     549         [ #  # ]:          0 :                 if (params->silence_threshold != 0)
     550                 :            :                         return -EINVAL;
     551                 :            :         } else {
     552         [ #  # ]:          0 :                 if (params->silence_size > params->silence_threshold)
     553                 :            :                         return -EINVAL;
     554         [ #  # ]:          0 :                 if (params->silence_threshold > runtime->buffer_size)
     555                 :            :                         return -EINVAL;
     556                 :            :         }
     557                 :            :         err = 0;
     558                 :            :         snd_pcm_stream_lock_irq(substream);
     559                 :          0 :         runtime->tstamp_mode = params->tstamp_mode;
     560                 :          0 :         runtime->period_step = params->period_step;
     561                 :          0 :         runtime->control->avail_min = params->avail_min;
     562                 :          0 :         runtime->start_threshold = params->start_threshold;
     563                 :          0 :         runtime->stop_threshold = params->stop_threshold;
     564                 :          0 :         runtime->silence_threshold = params->silence_threshold;
     565                 :          0 :         runtime->silence_size = params->silence_size;
     566                 :          0 :         params->boundary = runtime->boundary;
     567         [ #  # ]:          0 :         if (snd_pcm_running(substream)) {
     568 [ #  # ][ #  # ]:          0 :                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
     569                 :          0 :                     runtime->silence_size > 0)
     570                 :          0 :                         snd_pcm_playback_silence(substream, ULONG_MAX);
     571                 :          0 :                 err = snd_pcm_update_state(substream, runtime);
     572                 :            :         }
     573                 :            :         snd_pcm_stream_unlock_irq(substream);
     574                 :          0 :         return err;
     575                 :            : }
     576                 :            : 
     577                 :          0 : static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
     578                 :            :                                   struct snd_pcm_sw_params __user * _params)
     579                 :            : {
     580                 :            :         struct snd_pcm_sw_params params;
     581                 :            :         int err;
     582         [ #  # ]:          0 :         if (copy_from_user(&params, _params, sizeof(params)))
     583                 :            :                 return -EFAULT;
     584                 :          0 :         err = snd_pcm_sw_params(substream, &params);
     585         [ #  # ]:          0 :         if (copy_to_user(_params, &params, sizeof(params)))
     586                 :            :                 return -EFAULT;
     587                 :          0 :         return err;
     588                 :            : }
     589                 :            : 
     590                 :          0 : int snd_pcm_status(struct snd_pcm_substream *substream,
     591                 :            :                    struct snd_pcm_status *status)
     592                 :            : {
     593                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
     594                 :            : 
     595                 :            :         snd_pcm_stream_lock_irq(substream);
     596                 :          0 :         status->state = runtime->status->state;
     597                 :          0 :         status->suspended_state = runtime->status->suspended_state;
     598         [ #  # ]:          0 :         if (status->state == SNDRV_PCM_STATE_OPEN)
     599                 :            :                 goto _end;
     600                 :          0 :         status->trigger_tstamp = runtime->trigger_tstamp;
     601         [ #  # ]:          0 :         if (snd_pcm_running(substream)) {
     602                 :          0 :                 snd_pcm_update_hw_ptr(substream);
     603         [ #  # ]:          0 :                 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
     604                 :          0 :                         status->tstamp = runtime->status->tstamp;
     605                 :          0 :                         status->audio_tstamp =
     606                 :          0 :                                 runtime->status->audio_tstamp;
     607                 :          0 :                         goto _tstamp_end;
     608                 :            :                 }
     609                 :            :         }
     610                 :          0 :         snd_pcm_gettime(runtime, &status->tstamp);
     611                 :            :  _tstamp_end:
     612                 :          0 :         status->appl_ptr = runtime->control->appl_ptr;
     613                 :          0 :         status->hw_ptr = runtime->status->hw_ptr;
     614         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
     615                 :          0 :                 status->avail = snd_pcm_playback_avail(runtime);
     616         [ #  # ]:          0 :                 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
     617                 :            :                     runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
     618                 :          0 :                         status->delay = runtime->buffer_size - status->avail;
     619                 :          0 :                         status->delay += runtime->delay;
     620                 :            :                 } else
     621                 :          0 :                         status->delay = 0;
     622                 :            :         } else {
     623                 :          0 :                 status->avail = snd_pcm_capture_avail(runtime);
     624         [ #  # ]:          0 :                 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
     625                 :          0 :                         status->delay = status->avail + runtime->delay;
     626                 :            :                 else
     627                 :          0 :                         status->delay = 0;
     628                 :            :         }
     629                 :          0 :         status->avail_max = runtime->avail_max;
     630                 :          0 :         status->overrange = runtime->overrange;
     631                 :          0 :         runtime->avail_max = 0;
     632                 :          0 :         runtime->overrange = 0;
     633                 :            :  _end:
     634                 :            :         snd_pcm_stream_unlock_irq(substream);
     635                 :          0 :         return 0;
     636                 :            : }
     637                 :            : 
     638                 :          0 : static int snd_pcm_status_user(struct snd_pcm_substream *substream,
     639                 :            :                                struct snd_pcm_status __user * _status)
     640                 :            : {
     641                 :            :         struct snd_pcm_status status;
     642                 :            :         int res;
     643                 :            :         
     644                 :          0 :         memset(&status, 0, sizeof(status));
     645                 :          0 :         res = snd_pcm_status(substream, &status);
     646         [ #  # ]:          0 :         if (res < 0)
     647                 :            :                 return res;
     648         [ #  # ]:          0 :         if (copy_to_user(_status, &status, sizeof(status)))
     649                 :            :                 return -EFAULT;
     650                 :          0 :         return 0;
     651                 :            : }
     652                 :            : 
     653                 :          0 : static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
     654                 :            :                                 struct snd_pcm_channel_info * info)
     655                 :            : {
     656                 :            :         struct snd_pcm_runtime *runtime;
     657                 :            :         unsigned int channel;
     658                 :            :         
     659                 :          0 :         channel = info->channel;
     660                 :          0 :         runtime = substream->runtime;
     661                 :            :         snd_pcm_stream_lock_irq(substream);
     662         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
     663                 :            :                 snd_pcm_stream_unlock_irq(substream);
     664                 :          0 :                 return -EBADFD;
     665                 :            :         }
     666                 :            :         snd_pcm_stream_unlock_irq(substream);
     667         [ #  # ]:          0 :         if (channel >= runtime->channels)
     668                 :            :                 return -EINVAL;
     669                 :          0 :         memset(info, 0, sizeof(*info));
     670                 :          0 :         info->channel = channel;
     671                 :          0 :         return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info);
     672                 :            : }
     673                 :            : 
     674                 :          0 : static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
     675                 :            :                                      struct snd_pcm_channel_info __user * _info)
     676                 :            : {
     677                 :            :         struct snd_pcm_channel_info info;
     678                 :            :         int res;
     679                 :            :         
     680         [ #  # ]:          0 :         if (copy_from_user(&info, _info, sizeof(info)))
     681                 :            :                 return -EFAULT;
     682                 :          0 :         res = snd_pcm_channel_info(substream, &info);
     683         [ #  # ]:          0 :         if (res < 0)
     684                 :            :                 return res;
     685         [ #  # ]:          0 :         if (copy_to_user(_info, &info, sizeof(info)))
     686                 :            :                 return -EFAULT;
     687                 :          0 :         return 0;
     688                 :            : }
     689                 :            : 
     690                 :          0 : static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
     691                 :            : {
     692                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
     693         [ #  # ]:          0 :         if (runtime->trigger_master == NULL)
     694                 :          0 :                 return;
     695         [ #  # ]:          0 :         if (runtime->trigger_master == substream) {
     696                 :          0 :                 snd_pcm_gettime(runtime, &runtime->trigger_tstamp);
     697                 :            :         } else {
     698                 :          0 :                 snd_pcm_trigger_tstamp(runtime->trigger_master);
     699                 :          0 :                 runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp;
     700                 :            :         }
     701                 :          0 :         runtime->trigger_master = NULL;
     702                 :            : }
     703                 :            : 
     704                 :            : struct action_ops {
     705                 :            :         int (*pre_action)(struct snd_pcm_substream *substream, int state);
     706                 :            :         int (*do_action)(struct snd_pcm_substream *substream, int state);
     707                 :            :         void (*undo_action)(struct snd_pcm_substream *substream, int state);
     708                 :            :         void (*post_action)(struct snd_pcm_substream *substream, int state);
     709                 :            : };
     710                 :            : 
     711                 :            : /*
     712                 :            :  *  this functions is core for handling of linked stream
     713                 :            :  *  Note: the stream state might be changed also on failure
     714                 :            :  *  Note2: call with calling stream lock + link lock
     715                 :            :  */
     716                 :          0 : static int snd_pcm_action_group(struct action_ops *ops,
     717                 :            :                                 struct snd_pcm_substream *substream,
     718                 :            :                                 int state, int do_lock)
     719                 :            : {
     720                 :            :         struct snd_pcm_substream *s = NULL;
     721                 :            :         struct snd_pcm_substream *s1;
     722                 :            :         int res = 0;
     723                 :            : 
     724         [ #  # ]:          0 :         snd_pcm_group_for_each_entry(s, substream) {
     725         [ #  # ]:          0 :                 if (do_lock && s != substream)
     726                 :          0 :                         spin_lock_nested(&s->self_group.lock,
     727                 :            :                                          SINGLE_DEPTH_NESTING);
     728                 :          0 :                 res = ops->pre_action(s, state);
     729         [ #  # ]:          0 :                 if (res < 0)
     730                 :            :                         goto _unlock;
     731                 :            :         }
     732         [ #  # ]:          0 :         snd_pcm_group_for_each_entry(s, substream) {
     733                 :          0 :                 res = ops->do_action(s, state);
     734         [ #  # ]:          0 :                 if (res < 0) {
     735         [ #  # ]:          0 :                         if (ops->undo_action) {
     736         [ #  # ]:          0 :                                 snd_pcm_group_for_each_entry(s1, substream) {
     737         [ #  # ]:          0 :                                         if (s1 == s) /* failed stream */
     738                 :            :                                                 break;
     739                 :          0 :                                         ops->undo_action(s1, state);
     740                 :            :                                 }
     741                 :            :                         }
     742                 :            :                         s = NULL; /* unlock all */
     743                 :            :                         goto _unlock;
     744                 :            :                 }
     745                 :            :         }
     746         [ #  # ]:          0 :         snd_pcm_group_for_each_entry(s, substream) {
     747                 :          0 :                 ops->post_action(s, state);
     748                 :            :         }
     749                 :            :  _unlock:
     750         [ #  # ]:          0 :         if (do_lock) {
     751                 :            :                 /* unlock streams */
     752         [ #  # ]:          0 :                 snd_pcm_group_for_each_entry(s1, substream) {
     753         [ #  # ]:          0 :                         if (s1 != substream)
     754                 :            :                                 spin_unlock(&s1->self_group.lock);
     755         [ #  # ]:          0 :                         if (s1 == s)    /* end */
     756                 :            :                                 break;
     757                 :            :                 }
     758                 :            :         }
     759                 :          0 :         return res;
     760                 :            : }
     761                 :            : 
     762                 :            : /*
     763                 :            :  *  Note: call with stream lock
     764                 :            :  */
     765                 :          0 : static int snd_pcm_action_single(struct action_ops *ops,
     766                 :            :                                  struct snd_pcm_substream *substream,
     767                 :            :                                  int state)
     768                 :            : {
     769                 :            :         int res;
     770                 :            :         
     771                 :          0 :         res = ops->pre_action(substream, state);
     772         [ #  # ]:          0 :         if (res < 0)
     773                 :            :                 return res;
     774                 :          0 :         res = ops->do_action(substream, state);
     775         [ #  # ]:          0 :         if (res == 0)
     776                 :          0 :                 ops->post_action(substream, state);
     777         [ #  # ]:          0 :         else if (ops->undo_action)
     778                 :          0 :                 ops->undo_action(substream, state);
     779                 :          0 :         return res;
     780                 :            : }
     781                 :            : 
     782                 :            : /*
     783                 :            :  *  Note: call with stream lock
     784                 :            :  */
     785                 :          0 : static int snd_pcm_action(struct action_ops *ops,
     786                 :            :                           struct snd_pcm_substream *substream,
     787                 :            :                           int state)
     788                 :            : {
     789                 :            :         int res;
     790                 :            : 
     791         [ #  # ]:          0 :         if (snd_pcm_stream_linked(substream)) {
     792         [ #  # ]:          0 :                 if (!spin_trylock(&substream->group->lock)) {
     793                 :            :                         spin_unlock(&substream->self_group.lock);
     794                 :          0 :                         spin_lock(&substream->group->lock);
     795                 :            :                         spin_lock(&substream->self_group.lock);
     796                 :            :                 }
     797                 :          0 :                 res = snd_pcm_action_group(ops, substream, state, 1);
     798                 :          0 :                 spin_unlock(&substream->group->lock);
     799                 :            :         } else {
     800                 :          0 :                 res = snd_pcm_action_single(ops, substream, state);
     801                 :            :         }
     802                 :          0 :         return res;
     803                 :            : }
     804                 :            : 
     805                 :            : /*
     806                 :            :  *  Note: don't use any locks before
     807                 :            :  */
     808                 :          0 : static int snd_pcm_action_lock_irq(struct action_ops *ops,
     809                 :            :                                    struct snd_pcm_substream *substream,
     810                 :            :                                    int state)
     811                 :            : {
     812                 :            :         int res;
     813                 :            : 
     814                 :          0 :         read_lock_irq(&snd_pcm_link_rwlock);
     815         [ #  # ]:          0 :         if (snd_pcm_stream_linked(substream)) {
     816                 :            :                 spin_lock(&substream->group->lock);
     817                 :            :                 spin_lock(&substream->self_group.lock);
     818                 :          0 :                 res = snd_pcm_action_group(ops, substream, state, 1);
     819                 :            :                 spin_unlock(&substream->self_group.lock);
     820                 :          0 :                 spin_unlock(&substream->group->lock);
     821                 :            :         } else {
     822                 :            :                 spin_lock(&substream->self_group.lock);
     823                 :          0 :                 res = snd_pcm_action_single(ops, substream, state);
     824                 :            :                 spin_unlock(&substream->self_group.lock);
     825                 :            :         }
     826                 :            :         read_unlock_irq(&snd_pcm_link_rwlock);
     827                 :          0 :         return res;
     828                 :            : }
     829                 :            : 
     830                 :            : /*
     831                 :            :  */
     832                 :          0 : static int snd_pcm_action_nonatomic(struct action_ops *ops,
     833                 :            :                                     struct snd_pcm_substream *substream,
     834                 :            :                                     int state)
     835                 :            : {
     836                 :            :         int res;
     837                 :            : 
     838                 :          0 :         down_read(&snd_pcm_link_rwsem);
     839         [ #  # ]:          0 :         if (snd_pcm_stream_linked(substream))
     840                 :          0 :                 res = snd_pcm_action_group(ops, substream, state, 0);
     841                 :            :         else
     842                 :          0 :                 res = snd_pcm_action_single(ops, substream, state);
     843                 :          0 :         up_read(&snd_pcm_link_rwsem);
     844                 :          0 :         return res;
     845                 :            : }
     846                 :            : 
     847                 :            : /*
     848                 :            :  * start callbacks
     849                 :            :  */
     850                 :          0 : static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
     851                 :            : {
     852                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
     853         [ #  # ]:          0 :         if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
     854                 :            :                 return -EBADFD;
     855 [ #  # ][ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
     856                 :            :             !snd_pcm_playback_data(substream))
     857                 :            :                 return -EPIPE;
     858                 :          0 :         runtime->trigger_master = substream;
     859                 :          0 :         return 0;
     860                 :            : }
     861                 :            : 
     862                 :          0 : static int snd_pcm_do_start(struct snd_pcm_substream *substream, int state)
     863                 :            : {
     864 [ #  # ][ #  # ]:          0 :         if (substream->runtime->trigger_master != substream)
     865                 :            :                 return 0;
     866                 :          0 :         return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
     867                 :            : }
     868                 :            : 
     869                 :          0 : static void snd_pcm_undo_start(struct snd_pcm_substream *substream, int state)
     870                 :            : {
     871         [ #  # ]:          0 :         if (substream->runtime->trigger_master == substream)
     872                 :          0 :                 substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
     873                 :          0 : }
     874                 :            : 
     875                 :          0 : static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
     876                 :            : {
     877                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
     878                 :          0 :         snd_pcm_trigger_tstamp(substream);
     879                 :          0 :         runtime->hw_ptr_jiffies = jiffies;
     880                 :          0 :         runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / 
     881                 :          0 :                                                             runtime->rate;
     882                 :          0 :         runtime->status->state = state;
     883 [ #  # ][ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
     884                 :          0 :             runtime->silence_size > 0)
     885                 :          0 :                 snd_pcm_playback_silence(substream, ULONG_MAX);
     886         [ #  # ]:          0 :         if (substream->timer)
     887                 :          0 :                 snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTART,
     888                 :            :                                  &runtime->trigger_tstamp);
     889                 :          0 : }
     890                 :            : 
     891                 :            : static struct action_ops snd_pcm_action_start = {
     892                 :            :         .pre_action = snd_pcm_pre_start,
     893                 :            :         .do_action = snd_pcm_do_start,
     894                 :            :         .undo_action = snd_pcm_undo_start,
     895                 :            :         .post_action = snd_pcm_post_start
     896                 :            : };
     897                 :            : 
     898                 :            : /**
     899                 :            :  * snd_pcm_start - start all linked streams
     900                 :            :  * @substream: the PCM substream instance
     901                 :            :  *
     902                 :            :  * Return: Zero if successful, or a negative error code.
     903                 :            :  */
     904                 :          0 : int snd_pcm_start(struct snd_pcm_substream *substream)
     905                 :            : {
     906                 :          0 :         return snd_pcm_action(&snd_pcm_action_start, substream,
     907                 :            :                               SNDRV_PCM_STATE_RUNNING);
     908                 :            : }
     909                 :            : 
     910                 :            : /*
     911                 :            :  * stop callbacks
     912                 :            :  */
     913                 :          0 : static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
     914                 :            : {
     915                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
     916         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
     917                 :            :                 return -EBADFD;
     918                 :          0 :         runtime->trigger_master = substream;
     919                 :          0 :         return 0;
     920                 :            : }
     921                 :            : 
     922                 :          0 : static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
     923                 :            : {
     924 [ #  # ][ #  # ]:          0 :         if (substream->runtime->trigger_master == substream &&
     925                 :            :             snd_pcm_running(substream))
     926                 :          0 :                 substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
     927                 :          0 :         return 0; /* unconditonally stop all substreams */
     928                 :            : }
     929                 :            : 
     930                 :          0 : static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
     931                 :            : {
     932                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
     933         [ #  # ]:          0 :         if (runtime->status->state != state) {
     934                 :          0 :                 snd_pcm_trigger_tstamp(substream);
     935         [ #  # ]:          0 :                 if (substream->timer)
     936                 :          0 :                         snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP,
     937                 :            :                                          &runtime->trigger_tstamp);
     938                 :          0 :                 runtime->status->state = state;
     939                 :            :         }
     940                 :          0 :         wake_up(&runtime->sleep);
     941                 :          0 :         wake_up(&runtime->tsleep);
     942                 :          0 : }
     943                 :            : 
     944                 :            : static struct action_ops snd_pcm_action_stop = {
     945                 :            :         .pre_action = snd_pcm_pre_stop,
     946                 :            :         .do_action = snd_pcm_do_stop,
     947                 :            :         .post_action = snd_pcm_post_stop
     948                 :            : };
     949                 :            : 
     950                 :            : /**
     951                 :            :  * snd_pcm_stop - try to stop all running streams in the substream group
     952                 :            :  * @substream: the PCM substream instance
     953                 :            :  * @state: PCM state after stopping the stream
     954                 :            :  *
     955                 :            :  * The state of each stream is then changed to the given state unconditionally.
     956                 :            :  *
     957                 :            :  * Return: Zero if succesful, or a negative error code.
     958                 :            :  */
     959                 :          0 : int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
     960                 :            : {
     961                 :          0 :         return snd_pcm_action(&snd_pcm_action_stop, substream, state);
     962                 :            : }
     963                 :            : 
     964                 :            : EXPORT_SYMBOL(snd_pcm_stop);
     965                 :            : 
     966                 :            : /**
     967                 :            :  * snd_pcm_drain_done - stop the DMA only when the given stream is playback
     968                 :            :  * @substream: the PCM substream
     969                 :            :  *
     970                 :            :  * After stopping, the state is changed to SETUP.
     971                 :            :  * Unlike snd_pcm_stop(), this affects only the given stream.
     972                 :            :  *
     973                 :            :  * Return: Zero if succesful, or a negative error code.
     974                 :            :  */
     975                 :          0 : int snd_pcm_drain_done(struct snd_pcm_substream *substream)
     976                 :            : {
     977                 :          0 :         return snd_pcm_action_single(&snd_pcm_action_stop, substream,
     978                 :            :                                      SNDRV_PCM_STATE_SETUP);
     979                 :            : }
     980                 :            : 
     981                 :            : /*
     982                 :            :  * pause callbacks
     983                 :            :  */
     984                 :          0 : static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
     985                 :            : {
     986                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
     987         [ #  # ]:          0 :         if (!(runtime->info & SNDRV_PCM_INFO_PAUSE))
     988                 :            :                 return -ENOSYS;
     989         [ #  # ]:          0 :         if (push) {
     990         [ #  # ]:          0 :                 if (runtime->status->state != SNDRV_PCM_STATE_RUNNING)
     991                 :            :                         return -EBADFD;
     992         [ #  # ]:          0 :         } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED)
     993                 :            :                 return -EBADFD;
     994                 :          0 :         runtime->trigger_master = substream;
     995                 :          0 :         return 0;
     996                 :            : }
     997                 :            : 
     998                 :          0 : static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
     999                 :            : {
    1000         [ #  # ]:          0 :         if (substream->runtime->trigger_master != substream)
    1001                 :            :                 return 0;
    1002                 :            :         /* some drivers might use hw_ptr to recover from the pause -
    1003                 :            :            update the hw_ptr now */
    1004         [ #  # ]:          0 :         if (push)
    1005                 :          0 :                 snd_pcm_update_hw_ptr(substream);
    1006                 :            :         /* The jiffies check in snd_pcm_update_hw_ptr*() is done by
    1007                 :            :          * a delta between the current jiffies, this gives a large enough
    1008                 :            :          * delta, effectively to skip the check once.
    1009                 :            :          */
    1010                 :          0 :         substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
    1011         [ #  # ]:          0 :         return substream->ops->trigger(substream,
    1012                 :            :                                        push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
    1013                 :            :                                               SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
    1014                 :            : }
    1015                 :            : 
    1016                 :          0 : static void snd_pcm_undo_pause(struct snd_pcm_substream *substream, int push)
    1017                 :            : {
    1018         [ #  # ]:          0 :         if (substream->runtime->trigger_master == substream)
    1019         [ #  # ]:          0 :                 substream->ops->trigger(substream,
    1020                 :            :                                         push ? SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
    1021                 :            :                                         SNDRV_PCM_TRIGGER_PAUSE_PUSH);
    1022                 :          0 : }
    1023                 :            : 
    1024                 :          0 : static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
    1025                 :            : {
    1026                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1027                 :          0 :         snd_pcm_trigger_tstamp(substream);
    1028         [ #  # ]:          0 :         if (push) {
    1029                 :          0 :                 runtime->status->state = SNDRV_PCM_STATE_PAUSED;
    1030         [ #  # ]:          0 :                 if (substream->timer)
    1031                 :          0 :                         snd_timer_notify(substream->timer,
    1032                 :            :                                          SNDRV_TIMER_EVENT_MPAUSE,
    1033                 :            :                                          &runtime->trigger_tstamp);
    1034                 :          0 :                 wake_up(&runtime->sleep);
    1035                 :          0 :                 wake_up(&runtime->tsleep);
    1036                 :            :         } else {
    1037                 :          0 :                 runtime->status->state = SNDRV_PCM_STATE_RUNNING;
    1038         [ #  # ]:          0 :                 if (substream->timer)
    1039                 :          0 :                         snd_timer_notify(substream->timer,
    1040                 :            :                                          SNDRV_TIMER_EVENT_MCONTINUE,
    1041                 :            :                                          &runtime->trigger_tstamp);
    1042                 :            :         }
    1043                 :          0 : }
    1044                 :            : 
    1045                 :            : static struct action_ops snd_pcm_action_pause = {
    1046                 :            :         .pre_action = snd_pcm_pre_pause,
    1047                 :            :         .do_action = snd_pcm_do_pause,
    1048                 :            :         .undo_action = snd_pcm_undo_pause,
    1049                 :            :         .post_action = snd_pcm_post_pause
    1050                 :            : };
    1051                 :            : 
    1052                 :            : /*
    1053                 :            :  * Push/release the pause for all linked streams.
    1054                 :            :  */
    1055                 :            : static int snd_pcm_pause(struct snd_pcm_substream *substream, int push)
    1056                 :            : {
    1057                 :          0 :         return snd_pcm_action(&snd_pcm_action_pause, substream, push);
    1058                 :            : }
    1059                 :            : 
    1060                 :            : #ifdef CONFIG_PM
    1061                 :            : /* suspend */
    1062                 :            : 
    1063                 :          0 : static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
    1064                 :            : {
    1065                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1066         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
    1067                 :            :                 return -EBUSY;
    1068                 :          0 :         runtime->trigger_master = substream;
    1069                 :          0 :         return 0;
    1070                 :            : }
    1071                 :            : 
    1072                 :          0 : static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
    1073                 :            : {
    1074                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1075         [ #  # ]:          0 :         if (runtime->trigger_master != substream)
    1076                 :            :                 return 0;
    1077         [ #  # ]:          0 :         if (! snd_pcm_running(substream))
    1078                 :            :                 return 0;
    1079                 :          0 :         substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
    1080                 :          0 :         return 0; /* suspend unconditionally */
    1081                 :            : }
    1082                 :            : 
    1083                 :          0 : static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
    1084                 :            : {
    1085                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1086                 :          0 :         snd_pcm_trigger_tstamp(substream);
    1087         [ #  # ]:          0 :         if (substream->timer)
    1088                 :          0 :                 snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSUSPEND,
    1089                 :            :                                  &runtime->trigger_tstamp);
    1090                 :          0 :         runtime->status->suspended_state = runtime->status->state;
    1091                 :          0 :         runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
    1092                 :          0 :         wake_up(&runtime->sleep);
    1093                 :          0 :         wake_up(&runtime->tsleep);
    1094                 :          0 : }
    1095                 :            : 
    1096                 :            : static struct action_ops snd_pcm_action_suspend = {
    1097                 :            :         .pre_action = snd_pcm_pre_suspend,
    1098                 :            :         .do_action = snd_pcm_do_suspend,
    1099                 :            :         .post_action = snd_pcm_post_suspend
    1100                 :            : };
    1101                 :            : 
    1102                 :            : /**
    1103                 :            :  * snd_pcm_suspend - trigger SUSPEND to all linked streams
    1104                 :            :  * @substream: the PCM substream
    1105                 :            :  *
    1106                 :            :  * After this call, all streams are changed to SUSPENDED state.
    1107                 :            :  *
    1108                 :            :  * Return: Zero if successful (or @substream is %NULL), or a negative error
    1109                 :            :  * code.
    1110                 :            :  */
    1111                 :          0 : int snd_pcm_suspend(struct snd_pcm_substream *substream)
    1112                 :            : {
    1113                 :            :         int err;
    1114                 :            :         unsigned long flags;
    1115                 :            : 
    1116         [ #  # ]:          0 :         if (! substream)
    1117                 :            :                 return 0;
    1118                 :            : 
    1119                 :          0 :         snd_pcm_stream_lock_irqsave(substream, flags);
    1120                 :          0 :         err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
    1121                 :          0 :         snd_pcm_stream_unlock_irqrestore(substream, flags);
    1122                 :          0 :         return err;
    1123                 :            : }
    1124                 :            : 
    1125                 :            : EXPORT_SYMBOL(snd_pcm_suspend);
    1126                 :            : 
    1127                 :            : /**
    1128                 :            :  * snd_pcm_suspend_all - trigger SUSPEND to all substreams in the given pcm
    1129                 :            :  * @pcm: the PCM instance
    1130                 :            :  *
    1131                 :            :  * After this call, all streams are changed to SUSPENDED state.
    1132                 :            :  *
    1133                 :            :  * Return: Zero if successful (or @pcm is %NULL), or a negative error code.
    1134                 :            :  */
    1135                 :          0 : int snd_pcm_suspend_all(struct snd_pcm *pcm)
    1136                 :            : {
    1137                 :            :         struct snd_pcm_substream *substream;
    1138                 :            :         int stream, err = 0;
    1139                 :            : 
    1140         [ #  # ]:          0 :         if (! pcm)
    1141                 :            :                 return 0;
    1142                 :            : 
    1143         [ #  # ]:          0 :         for (stream = 0; stream < 2; stream++) {
    1144         [ #  # ]:          0 :                 for (substream = pcm->streams[stream].substream;
    1145                 :          0 :                      substream; substream = substream->next) {
    1146                 :            :                         /* FIXME: the open/close code should lock this as well */
    1147         [ #  # ]:          0 :                         if (substream->runtime == NULL)
    1148                 :          0 :                                 continue;
    1149                 :          0 :                         err = snd_pcm_suspend(substream);
    1150         [ #  # ]:          0 :                         if (err < 0 && err != -EBUSY)
    1151                 :            :                                 return err;
    1152                 :            :                 }
    1153                 :            :         }
    1154                 :            :         return 0;
    1155                 :            : }
    1156                 :            : 
    1157                 :            : EXPORT_SYMBOL(snd_pcm_suspend_all);
    1158                 :            : 
    1159                 :            : /* resume */
    1160                 :            : 
    1161                 :          0 : static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
    1162                 :            : {
    1163                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1164         [ #  # ]:          0 :         if (!(runtime->info & SNDRV_PCM_INFO_RESUME))
    1165                 :            :                 return -ENOSYS;
    1166                 :          0 :         runtime->trigger_master = substream;
    1167                 :          0 :         return 0;
    1168                 :            : }
    1169                 :            : 
    1170                 :          0 : static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
    1171                 :            : {
    1172                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1173         [ #  # ]:          0 :         if (runtime->trigger_master != substream)
    1174                 :            :                 return 0;
    1175                 :            :         /* DMA not running previously? */
    1176 [ #  # ][ #  # ]:          0 :         if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING &&
    1177         [ #  # ]:          0 :             (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING ||
    1178                 :          0 :              substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
    1179                 :            :                 return 0;
    1180                 :          0 :         return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
    1181                 :            : }
    1182                 :            : 
    1183                 :          0 : static void snd_pcm_undo_resume(struct snd_pcm_substream *substream, int state)
    1184                 :            : {
    1185 [ #  # ][ #  # ]:          0 :         if (substream->runtime->trigger_master == substream &&
    1186                 :            :             snd_pcm_running(substream))
    1187                 :          0 :                 substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
    1188                 :          0 : }
    1189                 :            : 
    1190                 :          0 : static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
    1191                 :            : {
    1192                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1193                 :          0 :         snd_pcm_trigger_tstamp(substream);
    1194         [ #  # ]:          0 :         if (substream->timer)
    1195                 :          0 :                 snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MRESUME,
    1196                 :            :                                  &runtime->trigger_tstamp);
    1197                 :          0 :         runtime->status->state = runtime->status->suspended_state;
    1198                 :          0 : }
    1199                 :            : 
    1200                 :            : static struct action_ops snd_pcm_action_resume = {
    1201                 :            :         .pre_action = snd_pcm_pre_resume,
    1202                 :            :         .do_action = snd_pcm_do_resume,
    1203                 :            :         .undo_action = snd_pcm_undo_resume,
    1204                 :            :         .post_action = snd_pcm_post_resume
    1205                 :            : };
    1206                 :            : 
    1207                 :          0 : static int snd_pcm_resume(struct snd_pcm_substream *substream)
    1208                 :            : {
    1209                 :          0 :         struct snd_card *card = substream->pcm->card;
    1210                 :            :         int res;
    1211                 :            : 
    1212                 :            :         snd_power_lock(card);
    1213         [ #  # ]:          0 :         if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
    1214                 :          0 :                 res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
    1215                 :            :         snd_power_unlock(card);
    1216                 :          0 :         return res;
    1217                 :            : }
    1218                 :            : 
    1219                 :            : #else
    1220                 :            : 
    1221                 :            : static int snd_pcm_resume(struct snd_pcm_substream *substream)
    1222                 :            : {
    1223                 :            :         return -ENOSYS;
    1224                 :            : }
    1225                 :            : 
    1226                 :            : #endif /* CONFIG_PM */
    1227                 :            : 
    1228                 :            : /*
    1229                 :            :  * xrun ioctl
    1230                 :            :  *
    1231                 :            :  * Change the RUNNING stream(s) to XRUN state.
    1232                 :            :  */
    1233                 :          0 : static int snd_pcm_xrun(struct snd_pcm_substream *substream)
    1234                 :            : {
    1235                 :          0 :         struct snd_card *card = substream->pcm->card;
    1236                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1237                 :            :         int result;
    1238                 :            : 
    1239                 :            :         snd_power_lock(card);
    1240         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
    1241                 :          0 :                 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
    1242         [ #  # ]:          0 :                 if (result < 0)
    1243                 :            :                         goto _unlock;
    1244                 :            :         }
    1245                 :            : 
    1246                 :            :         snd_pcm_stream_lock_irq(substream);
    1247      [ #  #  # ]:          0 :         switch (runtime->status->state) {
    1248                 :            :         case SNDRV_PCM_STATE_XRUN:
    1249                 :            :                 result = 0;     /* already there */
    1250                 :            :                 break;
    1251                 :            :         case SNDRV_PCM_STATE_RUNNING:
    1252                 :            :                 result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
    1253                 :          0 :                 break;
    1254                 :            :         default:
    1255                 :            :                 result = -EBADFD;
    1256                 :            :         }
    1257                 :            :         snd_pcm_stream_unlock_irq(substream);
    1258                 :            :  _unlock:
    1259                 :            :         snd_power_unlock(card);
    1260                 :          0 :         return result;
    1261                 :            : }
    1262                 :            : 
    1263                 :            : /*
    1264                 :            :  * reset ioctl
    1265                 :            :  */
    1266                 :          0 : static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
    1267                 :            : {
    1268                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1269 [ #  # ][ #  # ]:          0 :         switch (runtime->status->state) {
    1270                 :            :         case SNDRV_PCM_STATE_RUNNING:
    1271                 :            :         case SNDRV_PCM_STATE_PREPARED:
    1272                 :            :         case SNDRV_PCM_STATE_PAUSED:
    1273                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    1274                 :            :                 return 0;
    1275                 :            :         default:
    1276                 :          0 :                 return -EBADFD;
    1277                 :            :         }
    1278                 :            : }
    1279                 :            : 
    1280                 :          0 : static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
    1281                 :            : {
    1282                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1283                 :          0 :         int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
    1284         [ #  # ]:          0 :         if (err < 0)
    1285                 :            :                 return err;
    1286                 :          0 :         runtime->hw_ptr_base = 0;
    1287                 :          0 :         runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
    1288                 :          0 :                 runtime->status->hw_ptr % runtime->period_size;
    1289                 :          0 :         runtime->silence_start = runtime->status->hw_ptr;
    1290                 :          0 :         runtime->silence_filled = 0;
    1291                 :          0 :         return 0;
    1292                 :            : }
    1293                 :            : 
    1294                 :          0 : static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state)
    1295                 :            : {
    1296                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1297                 :          0 :         runtime->control->appl_ptr = runtime->status->hw_ptr;
    1298 [ #  # ][ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
    1299                 :          0 :             runtime->silence_size > 0)
    1300                 :          0 :                 snd_pcm_playback_silence(substream, ULONG_MAX);
    1301                 :          0 : }
    1302                 :            : 
    1303                 :            : static struct action_ops snd_pcm_action_reset = {
    1304                 :            :         .pre_action = snd_pcm_pre_reset,
    1305                 :            :         .do_action = snd_pcm_do_reset,
    1306                 :            :         .post_action = snd_pcm_post_reset
    1307                 :            : };
    1308                 :            : 
    1309                 :            : static int snd_pcm_reset(struct snd_pcm_substream *substream)
    1310                 :            : {
    1311                 :          0 :         return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
    1312                 :            : }
    1313                 :            : 
    1314                 :            : /*
    1315                 :            :  * prepare ioctl
    1316                 :            :  */
    1317                 :            : /* we use the second argument for updating f_flags */
    1318                 :          0 : static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
    1319                 :            :                                int f_flags)
    1320                 :            : {
    1321                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1322         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
    1323                 :            :             runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
    1324                 :            :                 return -EBADFD;
    1325         [ #  # ]:          0 :         if (snd_pcm_running(substream))
    1326                 :            :                 return -EBUSY;
    1327                 :          0 :         substream->f_flags = f_flags;
    1328                 :          0 :         return 0;
    1329                 :            : }
    1330                 :            : 
    1331                 :          0 : static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, int state)
    1332                 :            : {
    1333                 :            :         int err;
    1334                 :          0 :         err = substream->ops->prepare(substream);
    1335         [ #  # ]:          0 :         if (err < 0)
    1336                 :            :                 return err;
    1337                 :          0 :         return snd_pcm_do_reset(substream, 0);
    1338                 :            : }
    1339                 :            : 
    1340                 :          0 : static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
    1341                 :            : {
    1342                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1343                 :          0 :         runtime->control->appl_ptr = runtime->status->hw_ptr;
    1344                 :          0 :         snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
    1345                 :          0 : }
    1346                 :            : 
    1347                 :            : static struct action_ops snd_pcm_action_prepare = {
    1348                 :            :         .pre_action = snd_pcm_pre_prepare,
    1349                 :            :         .do_action = snd_pcm_do_prepare,
    1350                 :            :         .post_action = snd_pcm_post_prepare
    1351                 :            : };
    1352                 :            : 
    1353                 :            : /**
    1354                 :            :  * snd_pcm_prepare - prepare the PCM substream to be triggerable
    1355                 :            :  * @substream: the PCM substream instance
    1356                 :            :  * @file: file to refer f_flags
    1357                 :            :  *
    1358                 :            :  * Return: Zero if successful, or a negative error code.
    1359                 :            :  */
    1360                 :          0 : static int snd_pcm_prepare(struct snd_pcm_substream *substream,
    1361                 :            :                            struct file *file)
    1362                 :            : {
    1363                 :            :         int res;
    1364                 :          0 :         struct snd_card *card = substream->pcm->card;
    1365                 :            :         int f_flags;
    1366                 :            : 
    1367         [ #  # ]:          0 :         if (file)
    1368                 :          0 :                 f_flags = file->f_flags;
    1369                 :            :         else
    1370                 :          0 :                 f_flags = substream->f_flags;
    1371                 :            : 
    1372                 :            :         snd_power_lock(card);
    1373         [ #  # ]:          0 :         if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
    1374                 :          0 :                 res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
    1375                 :            :                                                substream, f_flags);
    1376                 :            :         snd_power_unlock(card);
    1377                 :          0 :         return res;
    1378                 :            : }
    1379                 :            : 
    1380                 :            : /*
    1381                 :            :  * drain ioctl
    1382                 :            :  */
    1383                 :            : 
    1384                 :          0 : static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
    1385                 :            : {
    1386                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1387 [ #  # ][ #  # ]:          0 :         switch (runtime->status->state) {
    1388                 :            :         case SNDRV_PCM_STATE_OPEN:
    1389                 :            :         case SNDRV_PCM_STATE_DISCONNECTED:
    1390                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    1391                 :            :                 return -EBADFD;
    1392                 :            :         }
    1393                 :          0 :         runtime->trigger_master = substream;
    1394                 :          0 :         return 0;
    1395                 :            : }
    1396                 :            : 
    1397                 :          0 : static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
    1398                 :            : {
    1399                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1400         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    1401   [ #  #  #  # ]:          0 :                 switch (runtime->status->state) {
    1402                 :            :                 case SNDRV_PCM_STATE_PREPARED:
    1403                 :            :                         /* start playback stream if possible */
    1404         [ #  # ]:          0 :                         if (! snd_pcm_playback_empty(substream)) {
    1405                 :            :                                 snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING);
    1406                 :          0 :                                 snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING);
    1407                 :            :                         }
    1408                 :            :                         break;
    1409                 :            :                 case SNDRV_PCM_STATE_RUNNING:
    1410                 :          0 :                         runtime->status->state = SNDRV_PCM_STATE_DRAINING;
    1411                 :          0 :                         break;
    1412                 :            :                 case SNDRV_PCM_STATE_XRUN:
    1413                 :          0 :                         runtime->status->state = SNDRV_PCM_STATE_SETUP;
    1414                 :          0 :                         break;
    1415                 :            :                 default:
    1416                 :            :                         break;
    1417                 :            :                 }
    1418                 :            :         } else {
    1419                 :            :                 /* stop running stream */
    1420         [ #  # ]:          0 :                 if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
    1421                 :            :                         int new_state = snd_pcm_capture_avail(runtime) > 0 ?
    1422         [ #  # ]:          0 :                                 SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
    1423                 :          0 :                         snd_pcm_do_stop(substream, new_state);
    1424                 :          0 :                         snd_pcm_post_stop(substream, new_state);
    1425                 :            :                 }
    1426                 :            :         }
    1427                 :          0 :         return 0;
    1428                 :            : }
    1429                 :            : 
    1430                 :          0 : static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int state)
    1431                 :            : {
    1432                 :          0 : }
    1433                 :            : 
    1434                 :            : static struct action_ops snd_pcm_action_drain_init = {
    1435                 :            :         .pre_action = snd_pcm_pre_drain_init,
    1436                 :            :         .do_action = snd_pcm_do_drain_init,
    1437                 :            :         .post_action = snd_pcm_post_drain_init
    1438                 :            : };
    1439                 :            : 
    1440                 :            : static int snd_pcm_drop(struct snd_pcm_substream *substream);
    1441                 :            : 
    1442                 :            : /*
    1443                 :            :  * Drain the stream(s).
    1444                 :            :  * When the substream is linked, sync until the draining of all playback streams
    1445                 :            :  * is finished.
    1446                 :            :  * After this call, all streams are supposed to be either SETUP or DRAINING
    1447                 :            :  * (capture only) state.
    1448                 :            :  */
    1449                 :          0 : static int snd_pcm_drain(struct snd_pcm_substream *substream,
    1450                 :            :                          struct file *file)
    1451                 :            : {
    1452                 :            :         struct snd_card *card;
    1453                 :            :         struct snd_pcm_runtime *runtime;
    1454                 :            :         struct snd_pcm_substream *s;
    1455                 :            :         wait_queue_t wait;
    1456                 :            :         int result = 0;
    1457                 :            :         int nonblock = 0;
    1458                 :            : 
    1459                 :          0 :         card = substream->pcm->card;
    1460                 :          0 :         runtime = substream->runtime;
    1461                 :            : 
    1462         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    1463                 :            :                 return -EBADFD;
    1464                 :            : 
    1465                 :            :         snd_power_lock(card);
    1466         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
    1467                 :          0 :                 result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
    1468         [ #  # ]:          0 :                 if (result < 0) {
    1469                 :            :                         snd_power_unlock(card);
    1470                 :          0 :                         return result;
    1471                 :            :                 }
    1472                 :            :         }
    1473                 :            : 
    1474         [ #  # ]:          0 :         if (file) {
    1475         [ #  # ]:          0 :                 if (file->f_flags & O_NONBLOCK)
    1476                 :            :                         nonblock = 1;
    1477         [ #  # ]:          0 :         } else if (substream->f_flags & O_NONBLOCK)
    1478                 :            :                 nonblock = 1;
    1479                 :            : 
    1480                 :          0 :         down_read(&snd_pcm_link_rwsem);
    1481                 :            :         snd_pcm_stream_lock_irq(substream);
    1482                 :            :         /* resume pause */
    1483         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
    1484                 :            :                 snd_pcm_pause(substream, 0);
    1485                 :            : 
    1486                 :            :         /* pre-start/stop - all running streams are changed to DRAINING state */
    1487                 :          0 :         result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
    1488         [ #  # ]:          0 :         if (result < 0)
    1489                 :            :                 goto unlock;
    1490                 :            :         /* in non-blocking, we don't wait in ioctl but let caller poll */
    1491         [ #  # ]:          0 :         if (nonblock) {
    1492                 :            :                 result = -EAGAIN;
    1493                 :            :                 goto unlock;
    1494                 :            :         }
    1495                 :            : 
    1496                 :            :         for (;;) {
    1497                 :            :                 long tout;
    1498                 :            :                 struct snd_pcm_runtime *to_check;
    1499         [ #  # ]:          0 :                 if (signal_pending(current)) {
    1500                 :            :                         result = -ERESTARTSYS;
    1501                 :            :                         break;
    1502                 :            :                 }
    1503                 :            :                 /* find a substream to drain */
    1504                 :            :                 to_check = NULL;
    1505         [ #  # ]:          0 :                 snd_pcm_group_for_each_entry(s, substream) {
    1506         [ #  # ]:          0 :                         if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
    1507                 :          0 :                                 continue;
    1508                 :          0 :                         runtime = s->runtime;
    1509         [ #  # ]:          0 :                         if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
    1510                 :            :                                 to_check = runtime;
    1511                 :            :                                 break;
    1512                 :            :                         }
    1513                 :            :                 }
    1514         [ #  # ]:          0 :                 if (!to_check)
    1515                 :            :                         break; /* all drained */
    1516                 :          0 :                 init_waitqueue_entry(&wait, current);
    1517                 :          0 :                 add_wait_queue(&to_check->sleep, &wait);
    1518                 :            :                 snd_pcm_stream_unlock_irq(substream);
    1519                 :          0 :                 up_read(&snd_pcm_link_rwsem);
    1520                 :            :                 snd_power_unlock(card);
    1521         [ #  # ]:          0 :                 if (runtime->no_period_wakeup)
    1522                 :            :                         tout = MAX_SCHEDULE_TIMEOUT;
    1523                 :            :                 else {
    1524                 :            :                         tout = 10;
    1525         [ #  # ]:          0 :                         if (runtime->rate) {
    1526                 :          0 :                                 long t = runtime->period_size * 2 / runtime->rate;
    1527                 :          0 :                                 tout = max(t, tout);
    1528                 :            :                         }
    1529                 :          0 :                         tout = msecs_to_jiffies(tout * 1000);
    1530                 :            :                 }
    1531                 :          0 :                 tout = schedule_timeout_interruptible(tout);
    1532                 :            :                 snd_power_lock(card);
    1533                 :          0 :                 down_read(&snd_pcm_link_rwsem);
    1534                 :            :                 snd_pcm_stream_lock_irq(substream);
    1535                 :          0 :                 remove_wait_queue(&to_check->sleep, &wait);
    1536         [ #  # ]:          0 :                 if (card->shutdown) {
    1537                 :            :                         result = -ENODEV;
    1538                 :            :                         break;
    1539                 :            :                 }
    1540         [ #  # ]:          0 :                 if (tout == 0) {
    1541         [ #  # ]:          0 :                         if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
    1542                 :            :                                 result = -ESTRPIPE;
    1543                 :            :                         else {
    1544                 :            :                                 snd_printd("playback drain error (DMA or IRQ trouble?)\n");
    1545                 :            :                                 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
    1546                 :            :                                 result = -EIO;
    1547                 :            :                         }
    1548                 :            :                         break;
    1549                 :            :                 }
    1550                 :            :         }
    1551                 :            : 
    1552                 :            :  unlock:
    1553                 :            :         snd_pcm_stream_unlock_irq(substream);
    1554                 :          0 :         up_read(&snd_pcm_link_rwsem);
    1555                 :            :         snd_power_unlock(card);
    1556                 :            : 
    1557                 :          0 :         return result;
    1558                 :            : }
    1559                 :            : 
    1560                 :            : /*
    1561                 :            :  * drop ioctl
    1562                 :            :  *
    1563                 :            :  * Immediately put all linked substreams into SETUP state.
    1564                 :            :  */
    1565                 :          0 : static int snd_pcm_drop(struct snd_pcm_substream *substream)
    1566                 :            : {
    1567                 :            :         struct snd_pcm_runtime *runtime;
    1568                 :            :         int result = 0;
    1569                 :            :         
    1570 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
    1571                 :            :                 return -ENXIO;
    1572                 :          0 :         runtime = substream->runtime;
    1573                 :            : 
    1574         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
    1575         [ #  # ]:          0 :             runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED ||
    1576                 :            :             runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
    1577                 :            :                 return -EBADFD;
    1578                 :            : 
    1579                 :            :         snd_pcm_stream_lock_irq(substream);
    1580                 :            :         /* resume pause */
    1581         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
    1582                 :            :                 snd_pcm_pause(substream, 0);
    1583                 :            : 
    1584                 :            :         snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
    1585                 :            :         /* runtime->control->appl_ptr = runtime->status->hw_ptr; */
    1586                 :            :         snd_pcm_stream_unlock_irq(substream);
    1587                 :            : 
    1588                 :          0 :         return result;
    1589                 :            : }
    1590                 :            : 
    1591                 :            : 
    1592                 :          0 : static bool is_pcm_file(struct file *file)
    1593                 :            : {
    1594                 :          0 :         struct inode *inode = file_inode(file);
    1595                 :            :         unsigned int minor;
    1596                 :            : 
    1597 [ #  # ][ #  # ]:          0 :         if (!S_ISCHR(inode->i_mode) || imajor(inode) != snd_major)
    1598                 :            :                 return false;
    1599                 :            :         minor = iminor(inode);
    1600   [ #  #  #  # ]:          0 :         return snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) ||
    1601                 :          0 :                 snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
    1602                 :            : }
    1603                 :            : 
    1604                 :            : /*
    1605                 :            :  * PCM link handling
    1606                 :            :  */
    1607                 :          0 : static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
    1608                 :            : {
    1609                 :            :         int res = 0;
    1610                 :            :         struct snd_pcm_file *pcm_file;
    1611                 :            :         struct snd_pcm_substream *substream1;
    1612                 :            :         struct snd_pcm_group *group;
    1613                 :          0 :         struct fd f = fdget(fd);
    1614                 :            : 
    1615         [ #  # ]:          0 :         if (!f.file)
    1616                 :            :                 return -EBADFD;
    1617         [ #  # ]:          0 :         if (!is_pcm_file(f.file)) {
    1618                 :            :                 res = -EBADFD;
    1619                 :            :                 goto _badf;
    1620                 :            :         }
    1621                 :          0 :         pcm_file = f.file->private_data;
    1622                 :          0 :         substream1 = pcm_file->substream;
    1623                 :            :         group = kmalloc(sizeof(*group), GFP_KERNEL);
    1624         [ #  # ]:          0 :         if (!group) {
    1625                 :            :                 res = -ENOMEM;
    1626                 :            :                 goto _nolock;
    1627                 :            :         }
    1628                 :          0 :         down_write(&snd_pcm_link_rwsem);
    1629                 :          0 :         write_lock_irq(&snd_pcm_link_rwlock);
    1630 [ #  # ][ #  # ]:          0 :         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
    1631                 :          0 :             substream->runtime->status->state != substream1->runtime->status->state) {
    1632                 :            :                 res = -EBADFD;
    1633                 :            :                 goto _end;
    1634                 :            :         }
    1635         [ #  # ]:          0 :         if (snd_pcm_stream_linked(substream1)) {
    1636                 :            :                 res = -EALREADY;
    1637                 :            :                 goto _end;
    1638                 :            :         }
    1639         [ #  # ]:          0 :         if (!snd_pcm_stream_linked(substream)) {
    1640                 :          0 :                 substream->group = group;
    1641                 :            :                 group = NULL;
    1642                 :          0 :                 spin_lock_init(&substream->group->lock);
    1643                 :          0 :                 INIT_LIST_HEAD(&substream->group->substreams);
    1644                 :          0 :                 list_add_tail(&substream->link_list, &substream->group->substreams);
    1645                 :          0 :                 substream->group->count = 1;
    1646                 :            :         }
    1647                 :          0 :         list_add_tail(&substream1->link_list, &substream->group->substreams);
    1648                 :          0 :         substream->group->count++;
    1649                 :          0 :         substream1->group = substream->group;
    1650                 :            :  _end:
    1651                 :            :         write_unlock_irq(&snd_pcm_link_rwlock);
    1652                 :          0 :         up_write(&snd_pcm_link_rwsem);
    1653                 :            :  _nolock:
    1654                 :          0 :         snd_card_unref(substream1->pcm->card);
    1655                 :          0 :         kfree(group);
    1656                 :            :  _badf:
    1657                 :            :         fdput(f);
    1658                 :          0 :         return res;
    1659                 :            : }
    1660                 :            : 
    1661                 :            : static void relink_to_local(struct snd_pcm_substream *substream)
    1662                 :            : {
    1663                 :          0 :         substream->group = &substream->self_group;
    1664                 :          0 :         INIT_LIST_HEAD(&substream->self_group.substreams);
    1665                 :          0 :         list_add_tail(&substream->link_list, &substream->self_group.substreams);
    1666                 :            : }
    1667                 :            : 
    1668                 :          0 : static int snd_pcm_unlink(struct snd_pcm_substream *substream)
    1669                 :            : {
    1670                 :            :         struct snd_pcm_substream *s;
    1671                 :            :         int res = 0;
    1672                 :            : 
    1673                 :          0 :         down_write(&snd_pcm_link_rwsem);
    1674                 :          0 :         write_lock_irq(&snd_pcm_link_rwlock);
    1675         [ #  # ]:          0 :         if (!snd_pcm_stream_linked(substream)) {
    1676                 :            :                 res = -EALREADY;
    1677                 :            :                 goto _end;
    1678                 :            :         }
    1679                 :            :         list_del(&substream->link_list);
    1680                 :          0 :         substream->group->count--;
    1681         [ #  # ]:          0 :         if (substream->group->count == 1) {       /* detach the last stream, too */
    1682         [ #  # ]:          0 :                 snd_pcm_group_for_each_entry(s, substream) {
    1683                 :            :                         relink_to_local(s);
    1684                 :            :                         break;
    1685                 :            :                 }
    1686                 :          0 :                 kfree(substream->group);
    1687                 :            :         }
    1688                 :            :         relink_to_local(substream);
    1689                 :            :        _end:
    1690                 :            :         write_unlock_irq(&snd_pcm_link_rwlock);
    1691                 :          0 :         up_write(&snd_pcm_link_rwsem);
    1692                 :          0 :         return res;
    1693                 :            : }
    1694                 :            : 
    1695                 :            : /*
    1696                 :            :  * hw configurator
    1697                 :            :  */
    1698                 :          0 : static int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params,
    1699                 :            :                                struct snd_pcm_hw_rule *rule)
    1700                 :            : {
    1701                 :            :         struct snd_interval t;
    1702                 :          0 :         snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
    1703                 :            :                      hw_param_interval_c(params, rule->deps[1]), &t);
    1704                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    1705                 :            : }
    1706                 :            : 
    1707                 :          0 : static int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
    1708                 :            :                                struct snd_pcm_hw_rule *rule)
    1709                 :            : {
    1710                 :            :         struct snd_interval t;
    1711                 :          0 :         snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
    1712                 :            :                      hw_param_interval_c(params, rule->deps[1]), &t);
    1713                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    1714                 :            : }
    1715                 :            : 
    1716                 :          0 : static int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params,
    1717                 :            :                                    struct snd_pcm_hw_rule *rule)
    1718                 :            : {
    1719                 :            :         struct snd_interval t;
    1720                 :          0 :         snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]),
    1721                 :            :                          hw_param_interval_c(params, rule->deps[1]),
    1722                 :          0 :                          (unsigned long) rule->private, &t);
    1723                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    1724                 :            : }
    1725                 :            : 
    1726                 :          0 : static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params,
    1727                 :            :                                    struct snd_pcm_hw_rule *rule)
    1728                 :            : {
    1729                 :            :         struct snd_interval t;
    1730                 :          0 :         snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
    1731                 :          0 :                          (unsigned long) rule->private,
    1732                 :            :                          hw_param_interval_c(params, rule->deps[1]), &t);
    1733                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    1734                 :            : }
    1735                 :            : 
    1736                 :          0 : static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
    1737                 :            :                                   struct snd_pcm_hw_rule *rule)
    1738                 :            : {
    1739                 :            :         unsigned int k;
    1740                 :          0 :         struct snd_interval *i = hw_param_interval(params, rule->deps[0]);
    1741                 :            :         struct snd_mask m;
    1742                 :          0 :         struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
    1743                 :            :         snd_mask_any(&m);
    1744         [ #  # ]:          0 :         for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
    1745                 :            :                 int bits;
    1746         [ #  # ]:          0 :                 if (! snd_mask_test(mask, k))
    1747                 :          0 :                         continue;
    1748                 :          0 :                 bits = snd_pcm_format_physical_width(k);
    1749         [ #  # ]:          0 :                 if (bits <= 0)
    1750                 :          0 :                         continue; /* ignore invalid formats */
    1751 [ #  # ][ #  # ]:          0 :                 if ((unsigned)bits < i->min || (unsigned)bits > i->max)
    1752                 :            :                         snd_mask_reset(&m, k);
    1753                 :            :         }
    1754                 :          0 :         return snd_mask_refine(mask, &m);
    1755                 :            : }
    1756                 :            : 
    1757                 :          0 : static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
    1758                 :            :                                        struct snd_pcm_hw_rule *rule)
    1759                 :            : {
    1760                 :            :         struct snd_interval t;
    1761                 :            :         unsigned int k;
    1762                 :          0 :         t.min = UINT_MAX;
    1763                 :          0 :         t.max = 0;
    1764                 :          0 :         t.openmin = 0;
    1765                 :          0 :         t.openmax = 0;
    1766         [ #  # ]:          0 :         for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
    1767                 :            :                 int bits;
    1768         [ #  # ]:          0 :                 if (! snd_mask_test(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), k))
    1769                 :          0 :                         continue;
    1770                 :          0 :                 bits = snd_pcm_format_physical_width(k);
    1771         [ #  # ]:          0 :                 if (bits <= 0)
    1772                 :          0 :                         continue; /* ignore invalid formats */
    1773         [ #  # ]:          0 :                 if (t.min > (unsigned)bits)
    1774                 :          0 :                         t.min = bits;
    1775         [ #  # ]:          0 :                 if (t.max < (unsigned)bits)
    1776                 :          0 :                         t.max = bits;
    1777                 :            :         }
    1778                 :          0 :         t.integer = 1;
    1779                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    1780                 :            : }
    1781                 :            : 
    1782                 :            : #if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
    1783                 :            : #error "Change this table"
    1784                 :            : #endif
    1785                 :            : 
    1786                 :            : static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
    1787                 :            :                                  48000, 64000, 88200, 96000, 176400, 192000 };
    1788                 :            : 
    1789                 :            : const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
    1790                 :            :         .count = ARRAY_SIZE(rates),
    1791                 :            :         .list = rates,
    1792                 :            : };
    1793                 :            : 
    1794                 :          0 : static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params,
    1795                 :            :                                 struct snd_pcm_hw_rule *rule)
    1796                 :            : {
    1797                 :          0 :         struct snd_pcm_hardware *hw = rule->private;
    1798                 :          0 :         return snd_interval_list(hw_param_interval(params, rule->var),
    1799                 :            :                                  snd_pcm_known_rates.count,
    1800                 :            :                                  snd_pcm_known_rates.list, hw->rates);
    1801                 :            : }               
    1802                 :            : 
    1803                 :          0 : static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
    1804                 :            :                                             struct snd_pcm_hw_rule *rule)
    1805                 :            : {
    1806                 :            :         struct snd_interval t;
    1807                 :          0 :         struct snd_pcm_substream *substream = rule->private;
    1808                 :          0 :         t.min = 0;
    1809                 :          0 :         t.max = substream->buffer_bytes_max;
    1810                 :          0 :         t.openmin = 0;
    1811                 :          0 :         t.openmax = 0;
    1812                 :          0 :         t.integer = 1;
    1813                 :          0 :         return snd_interval_refine(hw_param_interval(params, rule->var), &t);
    1814                 :            : }               
    1815                 :            : 
    1816                 :          0 : int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
    1817                 :            : {
    1818                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1819                 :            :         struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
    1820                 :            :         int k, err;
    1821                 :            : 
    1822         [ #  # ]:          0 :         for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
    1823                 :          0 :                 snd_mask_any(constrs_mask(constrs, k));
    1824                 :            :         }
    1825                 :            : 
    1826         [ #  # ]:          0 :         for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) {
    1827                 :          0 :                 snd_interval_any(constrs_interval(constrs, k));
    1828                 :            :         }
    1829                 :            : 
    1830                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_CHANNELS));
    1831                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_SIZE));
    1832                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_BUFFER_BYTES));
    1833                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_SAMPLE_BITS));
    1834                 :            :         snd_interval_setinteger(constrs_interval(constrs, SNDRV_PCM_HW_PARAM_FRAME_BITS));
    1835                 :            : 
    1836                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
    1837                 :            :                                    snd_pcm_hw_rule_format, NULL,
    1838                 :            :                                    SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
    1839         [ #  # ]:          0 :         if (err < 0)
    1840                 :            :                 return err;
    1841                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 
    1842                 :            :                                   snd_pcm_hw_rule_sample_bits, NULL,
    1843                 :            :                                   SNDRV_PCM_HW_PARAM_FORMAT, 
    1844                 :            :                                   SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
    1845         [ #  # ]:          0 :         if (err < 0)
    1846                 :            :                 return err;
    1847                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 
    1848                 :            :                                   snd_pcm_hw_rule_div, NULL,
    1849                 :            :                                   SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);
    1850         [ #  # ]:          0 :         if (err < 0)
    1851                 :            :                 return err;
    1852                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, 
    1853                 :            :                                   snd_pcm_hw_rule_mul, NULL,
    1854                 :            :                                   SNDRV_PCM_HW_PARAM_SAMPLE_BITS, SNDRV_PCM_HW_PARAM_CHANNELS, -1);
    1855         [ #  # ]:          0 :         if (err < 0)
    1856                 :            :                 return err;
    1857                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, 
    1858                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 8,
    1859                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
    1860         [ #  # ]:          0 :         if (err < 0)
    1861                 :            :                 return err;
    1862                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FRAME_BITS, 
    1863                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 8,
    1864                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
    1865         [ #  # ]:          0 :         if (err < 0)
    1866                 :            :                 return err;
    1867                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 
    1868                 :            :                                   snd_pcm_hw_rule_div, NULL,
    1869                 :            :                                   SNDRV_PCM_HW_PARAM_FRAME_BITS, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
    1870         [ #  # ]:          0 :         if (err < 0)
    1871                 :            :                 return err;
    1872                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 
    1873                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
    1874                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_TIME, -1);
    1875         [ #  # ]:          0 :         if (err < 0)
    1876                 :            :                 return err;
    1877                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 
    1878                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
    1879                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_BUFFER_TIME, -1);
    1880         [ #  # ]:          0 :         if (err < 0)
    1881                 :            :                 return err;
    1882                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS, 
    1883                 :            :                                   snd_pcm_hw_rule_div, NULL,
    1884                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
    1885         [ #  # ]:          0 :         if (err < 0)
    1886                 :            :                 return err;
    1887                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 
    1888                 :            :                                   snd_pcm_hw_rule_div, NULL,
    1889                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1);
    1890         [ #  # ]:          0 :         if (err < 0)
    1891                 :            :                 return err;
    1892                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 
    1893                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 8,
    1894                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
    1895         [ #  # ]:          0 :         if (err < 0)
    1896                 :            :                 return err;
    1897                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 
    1898                 :            :                                   snd_pcm_hw_rule_muldivk, (void*) 1000000,
    1899                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);
    1900         [ #  # ]:          0 :         if (err < 0)
    1901                 :            :                 return err;
    1902                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 
    1903                 :            :                                   snd_pcm_hw_rule_mul, NULL,
    1904                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_PERIODS, -1);
    1905         [ #  # ]:          0 :         if (err < 0)
    1906                 :            :                 return err;
    1907                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 
    1908                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 8,
    1909                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
    1910         [ #  # ]:          0 :         if (err < 0)
    1911                 :            :                 return err;
    1912                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 
    1913                 :            :                                   snd_pcm_hw_rule_muldivk, (void*) 1000000,
    1914                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_TIME, SNDRV_PCM_HW_PARAM_RATE, -1);
    1915         [ #  # ]:          0 :         if (err < 0)
    1916                 :            :                 return err;
    1917                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 
    1918                 :            :                                   snd_pcm_hw_rule_muldivk, (void*) 8,
    1919                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
    1920         [ #  # ]:          0 :         if (err < 0)
    1921                 :            :                 return err;
    1922                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 
    1923                 :            :                                   snd_pcm_hw_rule_muldivk, (void*) 8,
    1924                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_FRAME_BITS, -1);
    1925         [ #  # ]:          0 :         if (err < 0)
    1926                 :            :                 return err;
    1927                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 
    1928                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
    1929                 :            :                                   SNDRV_PCM_HW_PARAM_PERIOD_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);
    1930         [ #  # ]:          0 :         if (err < 0)
    1931                 :            :                 return err;
    1932                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 
    1933                 :            :                                   snd_pcm_hw_rule_mulkdiv, (void*) 1000000,
    1934                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_SIZE, SNDRV_PCM_HW_PARAM_RATE, -1);
    1935         [ #  # ]:          0 :         if (err < 0)
    1936                 :          0 :                 return err;
    1937                 :            :         return 0;
    1938                 :            : }
    1939                 :            : 
    1940                 :          0 : int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
    1941                 :            : {
    1942                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    1943                 :          0 :         struct snd_pcm_hardware *hw = &runtime->hw;
    1944                 :            :         int err;
    1945                 :            :         unsigned int mask = 0;
    1946                 :            : 
    1947         [ #  # ]:          0 :         if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
    1948                 :            :                 mask |= 1 << SNDRV_PCM_ACCESS_RW_INTERLEAVED;
    1949         [ #  # ]:          0 :         if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
    1950                 :          0 :                 mask |= 1 << SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;
    1951         [ #  # ]:          0 :         if (hw->info & SNDRV_PCM_INFO_MMAP) {
    1952         [ #  # ]:          0 :                 if (hw->info & SNDRV_PCM_INFO_INTERLEAVED)
    1953                 :          0 :                         mask |= 1 << SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
    1954         [ #  # ]:          0 :                 if (hw->info & SNDRV_PCM_INFO_NONINTERLEAVED)
    1955                 :          0 :                         mask |= 1 << SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED;
    1956         [ #  # ]:          0 :                 if (hw->info & SNDRV_PCM_INFO_COMPLEX)
    1957                 :          0 :                         mask |= 1 << SNDRV_PCM_ACCESS_MMAP_COMPLEX;
    1958                 :            :         }
    1959                 :          0 :         err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_ACCESS, mask);
    1960         [ #  # ]:          0 :         if (err < 0)
    1961                 :            :                 return err;
    1962                 :            : 
    1963                 :          0 :         err = snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, hw->formats);
    1964         [ #  # ]:          0 :         if (err < 0)
    1965                 :            :                 return err;
    1966                 :            : 
    1967                 :          0 :         err = snd_pcm_hw_constraint_mask(runtime, SNDRV_PCM_HW_PARAM_SUBFORMAT, 1 << SNDRV_PCM_SUBFORMAT_STD);
    1968         [ #  # ]:          0 :         if (err < 0)
    1969                 :            :                 return err;
    1970                 :            : 
    1971                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS,
    1972                 :            :                                            hw->channels_min, hw->channels_max);
    1973         [ #  # ]:          0 :         if (err < 0)
    1974                 :            :                 return err;
    1975                 :            : 
    1976                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE,
    1977                 :            :                                            hw->rate_min, hw->rate_max);
    1978         [ #  # ]:          0 :         if (err < 0)
    1979                 :            :                 return err;
    1980                 :            : 
    1981                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
    1982                 :            :                                            hw->period_bytes_min, hw->period_bytes_max);
    1983         [ #  # ]:          0 :         if (err < 0)
    1984                 :            :                 return err;
    1985                 :            : 
    1986                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS,
    1987                 :            :                                            hw->periods_min, hw->periods_max);
    1988         [ #  # ]:          0 :         if (err < 0)
    1989                 :            :                 return err;
    1990                 :            : 
    1991                 :          0 :         err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
    1992                 :            :                                            hw->period_bytes_min, hw->buffer_bytes_max);
    1993         [ #  # ]:          0 :         if (err < 0)
    1994                 :            :                 return err;
    1995                 :            : 
    1996                 :          0 :         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 
    1997                 :            :                                   snd_pcm_hw_rule_buffer_bytes_max, substream,
    1998                 :            :                                   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
    1999         [ #  # ]:          0 :         if (err < 0)
    2000                 :            :                 return err;
    2001                 :            : 
    2002                 :            :         /* FIXME: remove */
    2003         [ #  # ]:          0 :         if (runtime->dma_bytes) {
    2004                 :          0 :                 err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0, runtime->dma_bytes);
    2005         [ #  # ]:          0 :                 if (err < 0)
    2006                 :            :                         return err;
    2007                 :            :         }
    2008                 :            : 
    2009         [ #  # ]:          0 :         if (!(hw->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))) {
    2010                 :          0 :                 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 
    2011                 :            :                                           snd_pcm_hw_rule_rate, hw,
    2012                 :            :                                           SNDRV_PCM_HW_PARAM_RATE, -1);
    2013         [ #  # ]:          0 :                 if (err < 0)
    2014                 :            :                         return err;
    2015                 :            :         }
    2016                 :            : 
    2017                 :            :         /* FIXME: this belong to lowlevel */
    2018                 :          0 :         snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
    2019                 :            : 
    2020                 :          0 :         return 0;
    2021                 :            : }
    2022                 :            : 
    2023                 :          0 : static void pcm_release_private(struct snd_pcm_substream *substream)
    2024                 :            : {
    2025                 :          0 :         snd_pcm_unlink(substream);
    2026                 :          0 : }
    2027                 :            : 
    2028                 :          0 : void snd_pcm_release_substream(struct snd_pcm_substream *substream)
    2029                 :            : {
    2030                 :          0 :         substream->ref_count--;
    2031         [ #  # ]:          0 :         if (substream->ref_count > 0)
    2032                 :          0 :                 return;
    2033                 :            : 
    2034                 :          0 :         snd_pcm_drop(substream);
    2035         [ #  # ]:          0 :         if (substream->hw_opened) {
    2036         [ #  # ]:          0 :                 if (substream->ops->hw_free != NULL)
    2037                 :          0 :                         substream->ops->hw_free(substream);
    2038                 :          0 :                 substream->ops->close(substream);
    2039                 :          0 :                 substream->hw_opened = 0;
    2040                 :            :         }
    2041         [ #  # ]:          0 :         if (pm_qos_request_active(&substream->latency_pm_qos_req))
    2042                 :          0 :                 pm_qos_remove_request(&substream->latency_pm_qos_req);
    2043         [ #  # ]:          0 :         if (substream->pcm_release) {
    2044                 :          0 :                 substream->pcm_release(substream);
    2045                 :          0 :                 substream->pcm_release = NULL;
    2046                 :            :         }
    2047                 :          0 :         snd_pcm_detach_substream(substream);
    2048                 :            : }
    2049                 :            : 
    2050                 :            : EXPORT_SYMBOL(snd_pcm_release_substream);
    2051                 :            : 
    2052                 :          0 : int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
    2053                 :            :                            struct file *file,
    2054                 :            :                            struct snd_pcm_substream **rsubstream)
    2055                 :            : {
    2056                 :            :         struct snd_pcm_substream *substream;
    2057                 :            :         int err;
    2058                 :            : 
    2059                 :          0 :         err = snd_pcm_attach_substream(pcm, stream, file, &substream);
    2060         [ #  # ]:          0 :         if (err < 0)
    2061                 :            :                 return err;
    2062         [ #  # ]:          0 :         if (substream->ref_count > 1) {
    2063                 :          0 :                 *rsubstream = substream;
    2064                 :          0 :                 return 0;
    2065                 :            :         }
    2066                 :            : 
    2067                 :          0 :         err = snd_pcm_hw_constraints_init(substream);
    2068         [ #  # ]:          0 :         if (err < 0) {
    2069                 :            :                 snd_printd("snd_pcm_hw_constraints_init failed\n");
    2070                 :            :                 goto error;
    2071                 :            :         }
    2072                 :            : 
    2073         [ #  # ]:          0 :         if ((err = substream->ops->open(substream)) < 0)
    2074                 :            :                 goto error;
    2075                 :            : 
    2076                 :          0 :         substream->hw_opened = 1;
    2077                 :            : 
    2078                 :          0 :         err = snd_pcm_hw_constraints_complete(substream);
    2079         [ #  # ]:          0 :         if (err < 0) {
    2080                 :            :                 snd_printd("snd_pcm_hw_constraints_complete failed\n");
    2081                 :            :                 goto error;
    2082                 :            :         }
    2083                 :            : 
    2084                 :          0 :         *rsubstream = substream;
    2085                 :          0 :         return 0;
    2086                 :            : 
    2087                 :            :  error:
    2088                 :          0 :         snd_pcm_release_substream(substream);
    2089                 :          0 :         return err;
    2090                 :            : }
    2091                 :            : 
    2092                 :            : EXPORT_SYMBOL(snd_pcm_open_substream);
    2093                 :            : 
    2094                 :          0 : static int snd_pcm_open_file(struct file *file,
    2095                 :            :                              struct snd_pcm *pcm,
    2096                 :            :                              int stream)
    2097                 :            : {
    2098                 :            :         struct snd_pcm_file *pcm_file;
    2099                 :            :         struct snd_pcm_substream *substream;
    2100                 :            :         int err;
    2101                 :            : 
    2102                 :          0 :         err = snd_pcm_open_substream(pcm, stream, file, &substream);
    2103         [ #  # ]:          0 :         if (err < 0)
    2104                 :            :                 return err;
    2105                 :            : 
    2106                 :            :         pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
    2107         [ #  # ]:          0 :         if (pcm_file == NULL) {
    2108                 :          0 :                 snd_pcm_release_substream(substream);
    2109                 :          0 :                 return -ENOMEM;
    2110                 :            :         }
    2111                 :          0 :         pcm_file->substream = substream;
    2112         [ #  # ]:          0 :         if (substream->ref_count == 1) {
    2113                 :          0 :                 substream->file = pcm_file;
    2114                 :          0 :                 substream->pcm_release = pcm_release_private;
    2115                 :            :         }
    2116                 :          0 :         file->private_data = pcm_file;
    2117                 :            : 
    2118                 :          0 :         return 0;
    2119                 :            : }
    2120                 :            : 
    2121                 :          0 : static int snd_pcm_playback_open(struct inode *inode, struct file *file)
    2122                 :            : {
    2123                 :            :         struct snd_pcm *pcm;
    2124                 :          0 :         int err = nonseekable_open(inode, file);
    2125         [ #  # ]:          0 :         if (err < 0)
    2126                 :            :                 return err;
    2127                 :          0 :         pcm = snd_lookup_minor_data(iminor(inode),
    2128                 :            :                                     SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
    2129                 :          0 :         err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
    2130         [ #  # ]:          0 :         if (pcm)
    2131                 :          0 :                 snd_card_unref(pcm->card);
    2132                 :          0 :         return err;
    2133                 :            : }
    2134                 :            : 
    2135                 :          0 : static int snd_pcm_capture_open(struct inode *inode, struct file *file)
    2136                 :            : {
    2137                 :            :         struct snd_pcm *pcm;
    2138                 :          0 :         int err = nonseekable_open(inode, file);
    2139         [ #  # ]:          0 :         if (err < 0)
    2140                 :            :                 return err;
    2141                 :          0 :         pcm = snd_lookup_minor_data(iminor(inode),
    2142                 :            :                                     SNDRV_DEVICE_TYPE_PCM_CAPTURE);
    2143                 :          0 :         err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
    2144         [ #  # ]:          0 :         if (pcm)
    2145                 :          0 :                 snd_card_unref(pcm->card);
    2146                 :          0 :         return err;
    2147                 :            : }
    2148                 :            : 
    2149                 :          0 : static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
    2150                 :            : {
    2151                 :            :         int err;
    2152                 :            :         wait_queue_t wait;
    2153                 :            : 
    2154         [ #  # ]:          0 :         if (pcm == NULL) {
    2155                 :            :                 err = -ENODEV;
    2156                 :            :                 goto __error1;
    2157                 :            :         }
    2158                 :          0 :         err = snd_card_file_add(pcm->card, file);
    2159         [ #  # ]:          0 :         if (err < 0)
    2160                 :            :                 goto __error1;
    2161         [ #  # ]:          0 :         if (!try_module_get(pcm->card->module)) {
    2162                 :            :                 err = -EFAULT;
    2163                 :            :                 goto __error2;
    2164                 :            :         }
    2165                 :          0 :         init_waitqueue_entry(&wait, current);
    2166                 :          0 :         add_wait_queue(&pcm->open_wait, &wait);
    2167                 :          0 :         mutex_lock(&pcm->open_mutex);
    2168                 :            :         while (1) {
    2169                 :          0 :                 err = snd_pcm_open_file(file, pcm, stream);
    2170         [ #  # ]:          0 :                 if (err >= 0)
    2171                 :            :                         break;
    2172         [ #  # ]:          0 :                 if (err == -EAGAIN) {
    2173         [ #  # ]:          0 :                         if (file->f_flags & O_NONBLOCK) {
    2174                 :            :                                 err = -EBUSY;
    2175                 :            :                                 break;
    2176                 :            :                         }
    2177                 :            :                 } else
    2178                 :            :                         break;
    2179                 :          0 :                 set_current_state(TASK_INTERRUPTIBLE);
    2180                 :          0 :                 mutex_unlock(&pcm->open_mutex);
    2181                 :          0 :                 schedule();
    2182                 :          0 :                 mutex_lock(&pcm->open_mutex);
    2183         [ #  # ]:          0 :                 if (pcm->card->shutdown) {
    2184                 :            :                         err = -ENODEV;
    2185                 :            :                         break;
    2186                 :            :                 }
    2187         [ #  # ]:          0 :                 if (signal_pending(current)) {
    2188                 :            :                         err = -ERESTARTSYS;
    2189                 :            :                         break;
    2190                 :            :                 }
    2191                 :            :         }
    2192                 :          0 :         remove_wait_queue(&pcm->open_wait, &wait);
    2193                 :          0 :         mutex_unlock(&pcm->open_mutex);
    2194         [ #  # ]:          0 :         if (err < 0)
    2195                 :            :                 goto __error;
    2196                 :            :         return err;
    2197                 :            : 
    2198                 :            :       __error:
    2199                 :          0 :         module_put(pcm->card->module);
    2200                 :            :       __error2:
    2201                 :          0 :         snd_card_file_remove(pcm->card, file);
    2202                 :            :       __error1:
    2203                 :          0 :         return err;
    2204                 :            : }
    2205                 :            : 
    2206                 :          0 : static int snd_pcm_release(struct inode *inode, struct file *file)
    2207                 :            : {
    2208                 :            :         struct snd_pcm *pcm;
    2209                 :            :         struct snd_pcm_substream *substream;
    2210                 :            :         struct snd_pcm_file *pcm_file;
    2211                 :            : 
    2212                 :          0 :         pcm_file = file->private_data;
    2213                 :          0 :         substream = pcm_file->substream;
    2214         [ #  # ]:          0 :         if (snd_BUG_ON(!substream))
    2215                 :            :                 return -ENXIO;
    2216                 :          0 :         pcm = substream->pcm;
    2217                 :          0 :         mutex_lock(&pcm->open_mutex);
    2218                 :          0 :         snd_pcm_release_substream(substream);
    2219                 :          0 :         kfree(pcm_file);
    2220                 :          0 :         mutex_unlock(&pcm->open_mutex);
    2221                 :          0 :         wake_up(&pcm->open_wait);
    2222                 :          0 :         module_put(pcm->card->module);
    2223                 :          0 :         snd_card_file_remove(pcm->card, file);
    2224                 :          0 :         return 0;
    2225                 :            : }
    2226                 :            : 
    2227                 :          0 : static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
    2228                 :            :                                                  snd_pcm_uframes_t frames)
    2229                 :            : {
    2230                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2231                 :            :         snd_pcm_sframes_t appl_ptr;
    2232                 :            :         snd_pcm_sframes_t ret;
    2233                 :            :         snd_pcm_sframes_t hw_avail;
    2234                 :            : 
    2235         [ #  # ]:          0 :         if (frames == 0)
    2236                 :            :                 return 0;
    2237                 :            : 
    2238                 :            :         snd_pcm_stream_lock_irq(substream);
    2239   [ #  #  #  #  :          0 :         switch (runtime->status->state) {
                      # ]
    2240                 :            :         case SNDRV_PCM_STATE_PREPARED:
    2241                 :            :                 break;
    2242                 :            :         case SNDRV_PCM_STATE_DRAINING:
    2243                 :            :         case SNDRV_PCM_STATE_RUNNING:
    2244         [ #  # ]:          0 :                 if (snd_pcm_update_hw_ptr(substream) >= 0)
    2245                 :            :                         break;
    2246                 :            :                 /* Fall through */
    2247                 :            :         case SNDRV_PCM_STATE_XRUN:
    2248                 :            :                 ret = -EPIPE;
    2249                 :            :                 goto __end;
    2250                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    2251                 :            :                 ret = -ESTRPIPE;
    2252                 :            :                 goto __end;
    2253                 :            :         default:
    2254                 :            :                 ret = -EBADFD;
    2255                 :          0 :                 goto __end;
    2256                 :            :         }
    2257                 :            : 
    2258                 :            :         hw_avail = snd_pcm_playback_hw_avail(runtime);
    2259         [ #  # ]:          0 :         if (hw_avail <= 0) {
    2260                 :            :                 ret = 0;
    2261                 :            :                 goto __end;
    2262                 :            :         }
    2263         [ #  # ]:          0 :         if (frames > (snd_pcm_uframes_t)hw_avail)
    2264                 :            :                 frames = hw_avail;
    2265                 :          0 :         appl_ptr = runtime->control->appl_ptr - frames;
    2266         [ #  # ]:          0 :         if (appl_ptr < 0)
    2267                 :          0 :                 appl_ptr += runtime->boundary;
    2268                 :          0 :         runtime->control->appl_ptr = appl_ptr;
    2269                 :          0 :         ret = frames;
    2270                 :            :  __end:
    2271                 :            :         snd_pcm_stream_unlock_irq(substream);
    2272                 :          0 :         return ret;
    2273                 :            : }
    2274                 :            : 
    2275                 :          0 : static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,
    2276                 :            :                                                 snd_pcm_uframes_t frames)
    2277                 :            : {
    2278                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2279                 :            :         snd_pcm_sframes_t appl_ptr;
    2280                 :            :         snd_pcm_sframes_t ret;
    2281                 :            :         snd_pcm_sframes_t hw_avail;
    2282                 :            : 
    2283         [ #  # ]:          0 :         if (frames == 0)
    2284                 :            :                 return 0;
    2285                 :            : 
    2286                 :            :         snd_pcm_stream_lock_irq(substream);
    2287   [ #  #  #  #  :          0 :         switch (runtime->status->state) {
                      # ]
    2288                 :            :         case SNDRV_PCM_STATE_PREPARED:
    2289                 :            :         case SNDRV_PCM_STATE_DRAINING:
    2290                 :            :                 break;
    2291                 :            :         case SNDRV_PCM_STATE_RUNNING:
    2292         [ #  # ]:          0 :                 if (snd_pcm_update_hw_ptr(substream) >= 0)
    2293                 :            :                         break;
    2294                 :            :                 /* Fall through */
    2295                 :            :         case SNDRV_PCM_STATE_XRUN:
    2296                 :            :                 ret = -EPIPE;
    2297                 :            :                 goto __end;
    2298                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    2299                 :            :                 ret = -ESTRPIPE;
    2300                 :            :                 goto __end;
    2301                 :            :         default:
    2302                 :            :                 ret = -EBADFD;
    2303                 :          0 :                 goto __end;
    2304                 :            :         }
    2305                 :            : 
    2306                 :            :         hw_avail = snd_pcm_capture_hw_avail(runtime);
    2307         [ #  # ]:          0 :         if (hw_avail <= 0) {
    2308                 :            :                 ret = 0;
    2309                 :            :                 goto __end;
    2310                 :            :         }
    2311         [ #  # ]:          0 :         if (frames > (snd_pcm_uframes_t)hw_avail)
    2312                 :            :                 frames = hw_avail;
    2313                 :          0 :         appl_ptr = runtime->control->appl_ptr - frames;
    2314         [ #  # ]:          0 :         if (appl_ptr < 0)
    2315                 :          0 :                 appl_ptr += runtime->boundary;
    2316                 :          0 :         runtime->control->appl_ptr = appl_ptr;
    2317                 :          0 :         ret = frames;
    2318                 :            :  __end:
    2319                 :            :         snd_pcm_stream_unlock_irq(substream);
    2320                 :          0 :         return ret;
    2321                 :            : }
    2322                 :            : 
    2323                 :          0 : static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,
    2324                 :            :                                                   snd_pcm_uframes_t frames)
    2325                 :            : {
    2326                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2327                 :            :         snd_pcm_sframes_t appl_ptr;
    2328                 :            :         snd_pcm_sframes_t ret;
    2329                 :            :         snd_pcm_sframes_t avail;
    2330                 :            : 
    2331         [ #  # ]:          0 :         if (frames == 0)
    2332                 :            :                 return 0;
    2333                 :            : 
    2334                 :            :         snd_pcm_stream_lock_irq(substream);
    2335   [ #  #  #  #  :          0 :         switch (runtime->status->state) {
                      # ]
    2336                 :            :         case SNDRV_PCM_STATE_PREPARED:
    2337                 :            :         case SNDRV_PCM_STATE_PAUSED:
    2338                 :            :                 break;
    2339                 :            :         case SNDRV_PCM_STATE_DRAINING:
    2340                 :            :         case SNDRV_PCM_STATE_RUNNING:
    2341         [ #  # ]:          0 :                 if (snd_pcm_update_hw_ptr(substream) >= 0)
    2342                 :            :                         break;
    2343                 :            :                 /* Fall through */
    2344                 :            :         case SNDRV_PCM_STATE_XRUN:
    2345                 :            :                 ret = -EPIPE;
    2346                 :            :                 goto __end;
    2347                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    2348                 :            :                 ret = -ESTRPIPE;
    2349                 :            :                 goto __end;
    2350                 :            :         default:
    2351                 :            :                 ret = -EBADFD;
    2352                 :          0 :                 goto __end;
    2353                 :            :         }
    2354                 :            : 
    2355                 :            :         avail = snd_pcm_playback_avail(runtime);
    2356         [ #  # ]:          0 :         if (avail <= 0) {
    2357                 :            :                 ret = 0;
    2358                 :            :                 goto __end;
    2359                 :            :         }
    2360         [ #  # ]:          0 :         if (frames > (snd_pcm_uframes_t)avail)
    2361                 :            :                 frames = avail;
    2362                 :          0 :         appl_ptr = runtime->control->appl_ptr + frames;
    2363         [ #  # ]:          0 :         if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
    2364                 :          0 :                 appl_ptr -= runtime->boundary;
    2365                 :          0 :         runtime->control->appl_ptr = appl_ptr;
    2366                 :          0 :         ret = frames;
    2367                 :            :  __end:
    2368                 :            :         snd_pcm_stream_unlock_irq(substream);
    2369                 :          0 :         return ret;
    2370                 :            : }
    2371                 :            : 
    2372                 :          0 : static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream,
    2373                 :            :                                                  snd_pcm_uframes_t frames)
    2374                 :            : {
    2375                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2376                 :            :         snd_pcm_sframes_t appl_ptr;
    2377                 :            :         snd_pcm_sframes_t ret;
    2378                 :            :         snd_pcm_sframes_t avail;
    2379                 :            : 
    2380         [ #  # ]:          0 :         if (frames == 0)
    2381                 :            :                 return 0;
    2382                 :            : 
    2383                 :            :         snd_pcm_stream_lock_irq(substream);
    2384   [ #  #  #  #  :          0 :         switch (runtime->status->state) {
                      # ]
    2385                 :            :         case SNDRV_PCM_STATE_PREPARED:
    2386                 :            :         case SNDRV_PCM_STATE_DRAINING:
    2387                 :            :         case SNDRV_PCM_STATE_PAUSED:
    2388                 :            :                 break;
    2389                 :            :         case SNDRV_PCM_STATE_RUNNING:
    2390         [ #  # ]:          0 :                 if (snd_pcm_update_hw_ptr(substream) >= 0)
    2391                 :            :                         break;
    2392                 :            :                 /* Fall through */
    2393                 :            :         case SNDRV_PCM_STATE_XRUN:
    2394                 :            :                 ret = -EPIPE;
    2395                 :            :                 goto __end;
    2396                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    2397                 :            :                 ret = -ESTRPIPE;
    2398                 :            :                 goto __end;
    2399                 :            :         default:
    2400                 :            :                 ret = -EBADFD;
    2401                 :          0 :                 goto __end;
    2402                 :            :         }
    2403                 :            : 
    2404                 :            :         avail = snd_pcm_capture_avail(runtime);
    2405         [ #  # ]:          0 :         if (avail <= 0) {
    2406                 :            :                 ret = 0;
    2407                 :            :                 goto __end;
    2408                 :            :         }
    2409         [ #  # ]:          0 :         if (frames > (snd_pcm_uframes_t)avail)
    2410                 :            :                 frames = avail;
    2411                 :          0 :         appl_ptr = runtime->control->appl_ptr + frames;
    2412         [ #  # ]:          0 :         if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
    2413                 :          0 :                 appl_ptr -= runtime->boundary;
    2414                 :          0 :         runtime->control->appl_ptr = appl_ptr;
    2415                 :          0 :         ret = frames;
    2416                 :            :  __end:
    2417                 :            :         snd_pcm_stream_unlock_irq(substream);
    2418                 :          0 :         return ret;
    2419                 :            : }
    2420                 :            : 
    2421                 :          0 : static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
    2422                 :            : {
    2423                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2424                 :            :         int err;
    2425                 :            : 
    2426                 :            :         snd_pcm_stream_lock_irq(substream);
    2427   [ #  #  #  #  :          0 :         switch (runtime->status->state) {
                      # ]
    2428                 :            :         case SNDRV_PCM_STATE_DRAINING:
    2429         [ #  # ]:          0 :                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
    2430                 :            :                         goto __badfd;
    2431                 :            :                 /* Fall through */
    2432                 :            :         case SNDRV_PCM_STATE_RUNNING:
    2433         [ #  # ]:          0 :                 if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
    2434                 :            :                         break;
    2435                 :            :                 /* Fall through */
    2436                 :            :         case SNDRV_PCM_STATE_PREPARED:
    2437                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    2438                 :            :                 err = 0;
    2439                 :            :                 break;
    2440                 :            :         case SNDRV_PCM_STATE_XRUN:
    2441                 :            :                 err = -EPIPE;
    2442                 :            :                 break;
    2443                 :            :         default:
    2444                 :            :               __badfd:
    2445                 :            :                 err = -EBADFD;
    2446                 :          0 :                 break;
    2447                 :            :         }
    2448                 :            :         snd_pcm_stream_unlock_irq(substream);
    2449                 :          0 :         return err;
    2450                 :            : }
    2451                 :            :                 
    2452                 :          0 : static int snd_pcm_delay(struct snd_pcm_substream *substream,
    2453                 :            :                          snd_pcm_sframes_t __user *res)
    2454                 :            : {
    2455                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2456                 :            :         int err;
    2457                 :            :         snd_pcm_sframes_t n = 0;
    2458                 :            : 
    2459                 :            :         snd_pcm_stream_lock_irq(substream);
    2460   [ #  #  #  #  :          0 :         switch (runtime->status->state) {
                      # ]
    2461                 :            :         case SNDRV_PCM_STATE_DRAINING:
    2462         [ #  # ]:          0 :                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
    2463                 :            :                         goto __badfd;
    2464                 :            :                 /* Fall through */
    2465                 :            :         case SNDRV_PCM_STATE_RUNNING:
    2466         [ #  # ]:          0 :                 if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
    2467                 :            :                         break;
    2468                 :            :                 /* Fall through */
    2469                 :            :         case SNDRV_PCM_STATE_PREPARED:
    2470                 :            :         case SNDRV_PCM_STATE_SUSPENDED:
    2471                 :            :                 err = 0;
    2472         [ #  # ]:          0 :                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    2473                 :            :                         n = snd_pcm_playback_hw_avail(runtime);
    2474                 :            :                 else
    2475                 :            :                         n = snd_pcm_capture_avail(runtime);
    2476                 :          0 :                 n += runtime->delay;
    2477                 :          0 :                 break;
    2478                 :            :         case SNDRV_PCM_STATE_XRUN:
    2479                 :            :                 err = -EPIPE;
    2480                 :            :                 break;
    2481                 :            :         default:
    2482                 :            :               __badfd:
    2483                 :            :                 err = -EBADFD;
    2484                 :          0 :                 break;
    2485                 :            :         }
    2486                 :            :         snd_pcm_stream_unlock_irq(substream);
    2487         [ #  # ]:          0 :         if (!err)
    2488         [ #  # ]:          0 :                 if (put_user(n, res))
    2489                 :            :                         err = -EFAULT;
    2490                 :          0 :         return err;
    2491                 :            : }
    2492                 :            :                 
    2493                 :          0 : static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
    2494                 :            :                             struct snd_pcm_sync_ptr __user *_sync_ptr)
    2495                 :            : {
    2496                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2497                 :            :         struct snd_pcm_sync_ptr sync_ptr;
    2498                 :            :         volatile struct snd_pcm_mmap_status *status;
    2499                 :            :         volatile struct snd_pcm_mmap_control *control;
    2500                 :            :         int err;
    2501                 :            : 
    2502                 :          0 :         memset(&sync_ptr, 0, sizeof(sync_ptr));
    2503         [ #  # ]:          0 :         if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags)))
    2504                 :            :                 return -EFAULT;
    2505         [ #  # ]:          0 :         if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct snd_pcm_mmap_control)))
    2506                 :            :                 return -EFAULT; 
    2507                 :          0 :         status = runtime->status;
    2508                 :          0 :         control = runtime->control;
    2509         [ #  # ]:          0 :         if (sync_ptr.flags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
    2510                 :          0 :                 err = snd_pcm_hwsync(substream);
    2511         [ #  # ]:          0 :                 if (err < 0)
    2512                 :            :                         return err;
    2513                 :            :         }
    2514                 :            :         snd_pcm_stream_lock_irq(substream);
    2515         [ #  # ]:          0 :         if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
    2516                 :          0 :                 control->appl_ptr = sync_ptr.c.control.appl_ptr;
    2517                 :            :         else
    2518                 :          0 :                 sync_ptr.c.control.appl_ptr = control->appl_ptr;
    2519         [ #  # ]:          0 :         if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
    2520                 :          0 :                 control->avail_min = sync_ptr.c.control.avail_min;
    2521                 :            :         else
    2522                 :          0 :                 sync_ptr.c.control.avail_min = control->avail_min;
    2523                 :          0 :         sync_ptr.s.status.state = status->state;
    2524                 :          0 :         sync_ptr.s.status.hw_ptr = status->hw_ptr;
    2525                 :          0 :         sync_ptr.s.status.tstamp = status->tstamp;
    2526                 :          0 :         sync_ptr.s.status.suspended_state = status->suspended_state;
    2527                 :            :         snd_pcm_stream_unlock_irq(substream);
    2528         [ #  # ]:          0 :         if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
    2529                 :            :                 return -EFAULT;
    2530                 :          0 :         return 0;
    2531                 :            : }
    2532                 :            : 
    2533                 :          0 : static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
    2534                 :            : {
    2535                 :          0 :         struct snd_pcm_runtime *runtime = substream->runtime;
    2536                 :            :         int arg;
    2537                 :            :         
    2538         [ #  # ]:          0 :         if (get_user(arg, _arg))
    2539                 :            :                 return -EFAULT;
    2540         [ #  # ]:          0 :         if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
    2541                 :            :                 return -EINVAL;
    2542                 :          0 :         runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
    2543         [ #  # ]:          0 :         if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
    2544                 :          0 :                 runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
    2545                 :            :         return 0;
    2546                 :            : }
    2547                 :            :                 
    2548                 :          0 : static int snd_pcm_common_ioctl1(struct file *file,
    2549                 :          0 :                                  struct snd_pcm_substream *substream,
    2550                 :            :                                  unsigned int cmd, void __user *arg)
    2551                 :            : {
    2552   [ #  #  #  #  :          0 :         switch (cmd) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2553                 :            :         case SNDRV_PCM_IOCTL_PVERSION:
    2554         [ #  # ]:          0 :                 return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
    2555                 :            :         case SNDRV_PCM_IOCTL_INFO:
    2556                 :          0 :                 return snd_pcm_info_user(substream, arg);
    2557                 :            :         case SNDRV_PCM_IOCTL_TSTAMP:    /* just for compatibility */
    2558                 :            :                 return 0;
    2559                 :            :         case SNDRV_PCM_IOCTL_TTSTAMP:
    2560                 :          0 :                 return snd_pcm_tstamp(substream, arg);
    2561                 :            :         case SNDRV_PCM_IOCTL_HW_REFINE:
    2562                 :          0 :                 return snd_pcm_hw_refine_user(substream, arg);
    2563                 :            :         case SNDRV_PCM_IOCTL_HW_PARAMS:
    2564                 :          0 :                 return snd_pcm_hw_params_user(substream, arg);
    2565                 :            :         case SNDRV_PCM_IOCTL_HW_FREE:
    2566                 :          0 :                 return snd_pcm_hw_free(substream);
    2567                 :            :         case SNDRV_PCM_IOCTL_SW_PARAMS:
    2568                 :          0 :                 return snd_pcm_sw_params_user(substream, arg);
    2569                 :            :         case SNDRV_PCM_IOCTL_STATUS:
    2570                 :          0 :                 return snd_pcm_status_user(substream, arg);
    2571                 :            :         case SNDRV_PCM_IOCTL_CHANNEL_INFO:
    2572                 :          0 :                 return snd_pcm_channel_info_user(substream, arg);
    2573                 :            :         case SNDRV_PCM_IOCTL_PREPARE:
    2574                 :          0 :                 return snd_pcm_prepare(substream, file);
    2575                 :            :         case SNDRV_PCM_IOCTL_RESET:
    2576                 :          0 :                 return snd_pcm_reset(substream);
    2577                 :            :         case SNDRV_PCM_IOCTL_START:
    2578                 :          0 :                 return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING);
    2579                 :            :         case SNDRV_PCM_IOCTL_LINK:
    2580                 :          0 :                 return snd_pcm_link(substream, (int)(unsigned long) arg);
    2581                 :            :         case SNDRV_PCM_IOCTL_UNLINK:
    2582                 :          0 :                 return snd_pcm_unlink(substream);
    2583                 :            :         case SNDRV_PCM_IOCTL_RESUME:
    2584                 :          0 :                 return snd_pcm_resume(substream);
    2585                 :            :         case SNDRV_PCM_IOCTL_XRUN:
    2586                 :          0 :                 return snd_pcm_xrun(substream);
    2587                 :            :         case SNDRV_PCM_IOCTL_HWSYNC:
    2588                 :          0 :                 return snd_pcm_hwsync(substream);
    2589                 :            :         case SNDRV_PCM_IOCTL_DELAY:
    2590                 :          0 :                 return snd_pcm_delay(substream, arg);
    2591                 :            :         case SNDRV_PCM_IOCTL_SYNC_PTR:
    2592                 :          0 :                 return snd_pcm_sync_ptr(substream, arg);
    2593                 :            : #ifdef CONFIG_SND_SUPPORT_OLD_API
    2594                 :            :         case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
    2595                 :          0 :                 return snd_pcm_hw_refine_old_user(substream, arg);
    2596                 :            :         case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
    2597                 :          0 :                 return snd_pcm_hw_params_old_user(substream, arg);
    2598                 :            : #endif
    2599                 :            :         case SNDRV_PCM_IOCTL_DRAIN:
    2600                 :          0 :                 return snd_pcm_drain(substream, file);
    2601                 :            :         case SNDRV_PCM_IOCTL_DROP:
    2602                 :          0 :                 return snd_pcm_drop(substream);
    2603                 :            :         case SNDRV_PCM_IOCTL_PAUSE:
    2604                 :            :         {
    2605                 :            :                 int res;
    2606                 :            :                 snd_pcm_stream_lock_irq(substream);
    2607                 :          0 :                 res = snd_pcm_pause(substream, (int)(unsigned long)arg);
    2608                 :            :                 snd_pcm_stream_unlock_irq(substream);
    2609                 :          0 :                 return res;
    2610                 :            :         }
    2611                 :            :         }
    2612                 :            :         snd_printd("unknown ioctl = 0x%x\n", cmd);
    2613                 :          0 :         return -ENOTTY;
    2614                 :            : }
    2615                 :            : 
    2616                 :          0 : static int snd_pcm_playback_ioctl1(struct file *file,
    2617                 :            :                                    struct snd_pcm_substream *substream,
    2618                 :            :                                    unsigned int cmd, void __user *arg)
    2619                 :            : {
    2620         [ #  # ]:          0 :         if (snd_BUG_ON(!substream))
    2621                 :            :                 return -ENXIO;
    2622         [ #  # ]:          0 :         if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
    2623                 :            :                 return -EINVAL;
    2624   [ #  #  #  #  :          0 :         switch (cmd) {
                      # ]
    2625                 :            :         case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
    2626                 :            :         {
    2627                 :            :                 struct snd_xferi xferi;
    2628                 :            :                 struct snd_xferi __user *_xferi = arg;
    2629                 :          0 :                 struct snd_pcm_runtime *runtime = substream->runtime;
    2630                 :            :                 snd_pcm_sframes_t result;
    2631         [ #  # ]:          0 :                 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    2632                 :            :                         return -EBADFD;
    2633         [ #  # ]:          0 :                 if (put_user(0, &_xferi->result))
    2634                 :            :                         return -EFAULT;
    2635         [ #  # ]:          0 :                 if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
    2636                 :            :                         return -EFAULT;
    2637                 :          0 :                 result = snd_pcm_lib_write(substream, xferi.buf, xferi.frames);
    2638                 :          0 :                 __put_user(result, &_xferi->result);
    2639                 :          0 :                 return result < 0 ? result : 0;
    2640                 :            :         }
    2641                 :            :         case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
    2642                 :            :         {
    2643                 :            :                 struct snd_xfern xfern;
    2644                 :            :                 struct snd_xfern __user *_xfern = arg;
    2645                 :          0 :                 struct snd_pcm_runtime *runtime = substream->runtime;
    2646                 :            :                 void __user **bufs;
    2647                 :            :                 snd_pcm_sframes_t result;
    2648         [ #  # ]:          0 :                 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    2649                 :            :                         return -EBADFD;
    2650         [ #  # ]:          0 :                 if (runtime->channels > 128)
    2651                 :            :                         return -EINVAL;
    2652         [ #  # ]:          0 :                 if (put_user(0, &_xfern->result))
    2653                 :            :                         return -EFAULT;
    2654         [ #  # ]:          0 :                 if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
    2655                 :            :                         return -EFAULT;
    2656                 :            : 
    2657                 :          0 :                 bufs = memdup_user(xfern.bufs,
    2658                 :          0 :                                    sizeof(void *) * runtime->channels);
    2659         [ #  # ]:          0 :                 if (IS_ERR(bufs))
    2660                 :          0 :                         return PTR_ERR(bufs);
    2661                 :          0 :                 result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
    2662                 :          0 :                 kfree(bufs);
    2663                 :          0 :                 __put_user(result, &_xfern->result);
    2664                 :          0 :                 return result < 0 ? result : 0;
    2665                 :            :         }
    2666                 :            :         case SNDRV_PCM_IOCTL_REWIND:
    2667                 :            :         {
    2668                 :            :                 snd_pcm_uframes_t frames;
    2669                 :            :                 snd_pcm_uframes_t __user *_frames = arg;
    2670                 :            :                 snd_pcm_sframes_t result;
    2671         [ #  # ]:          0 :                 if (get_user(frames, _frames))
    2672                 :            :                         return -EFAULT;
    2673         [ #  # ]:          0 :                 if (put_user(0, _frames))
    2674                 :            :                         return -EFAULT;
    2675                 :          0 :                 result = snd_pcm_playback_rewind(substream, frames);
    2676                 :          0 :                 __put_user(result, _frames);
    2677                 :          0 :                 return result < 0 ? result : 0;
    2678                 :            :         }
    2679                 :            :         case SNDRV_PCM_IOCTL_FORWARD:
    2680                 :            :         {
    2681                 :            :                 snd_pcm_uframes_t frames;
    2682                 :            :                 snd_pcm_uframes_t __user *_frames = arg;
    2683                 :            :                 snd_pcm_sframes_t result;
    2684         [ #  # ]:          0 :                 if (get_user(frames, _frames))
    2685                 :            :                         return -EFAULT;
    2686         [ #  # ]:          0 :                 if (put_user(0, _frames))
    2687                 :            :                         return -EFAULT;
    2688                 :          0 :                 result = snd_pcm_playback_forward(substream, frames);
    2689                 :          0 :                 __put_user(result, _frames);
    2690                 :          0 :                 return result < 0 ? result : 0;
    2691                 :            :         }
    2692                 :            :         }
    2693                 :          0 :         return snd_pcm_common_ioctl1(file, substream, cmd, arg);
    2694                 :            : }
    2695                 :            : 
    2696                 :          0 : static int snd_pcm_capture_ioctl1(struct file *file,
    2697                 :            :                                   struct snd_pcm_substream *substream,
    2698                 :            :                                   unsigned int cmd, void __user *arg)
    2699                 :            : {
    2700         [ #  # ]:          0 :         if (snd_BUG_ON(!substream))
    2701                 :            :                 return -ENXIO;
    2702         [ #  # ]:          0 :         if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE))
    2703                 :            :                 return -EINVAL;
    2704   [ #  #  #  #  :          0 :         switch (cmd) {
                      # ]
    2705                 :            :         case SNDRV_PCM_IOCTL_READI_FRAMES:
    2706                 :            :         {
    2707                 :            :                 struct snd_xferi xferi;
    2708                 :            :                 struct snd_xferi __user *_xferi = arg;
    2709                 :          0 :                 struct snd_pcm_runtime *runtime = substream->runtime;
    2710                 :            :                 snd_pcm_sframes_t result;
    2711         [ #  # ]:          0 :                 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    2712                 :            :                         return -EBADFD;
    2713         [ #  # ]:          0 :                 if (put_user(0, &_xferi->result))
    2714                 :            :                         return -EFAULT;
    2715         [ #  # ]:          0 :                 if (copy_from_user(&xferi, _xferi, sizeof(xferi)))
    2716                 :            :                         return -EFAULT;
    2717                 :          0 :                 result = snd_pcm_lib_read(substream, xferi.buf, xferi.frames);
    2718                 :          0 :                 __put_user(result, &_xferi->result);
    2719                 :          0 :                 return result < 0 ? result : 0;
    2720                 :            :         }
    2721                 :            :         case SNDRV_PCM_IOCTL_READN_FRAMES:
    2722                 :            :         {
    2723                 :            :                 struct snd_xfern xfern;
    2724                 :            :                 struct snd_xfern __user *_xfern = arg;
    2725                 :          0 :                 struct snd_pcm_runtime *runtime = substream->runtime;
    2726                 :            :                 void *bufs;
    2727                 :            :                 snd_pcm_sframes_t result;
    2728         [ #  # ]:          0 :                 if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    2729                 :            :                         return -EBADFD;
    2730         [ #  # ]:          0 :                 if (runtime->channels > 128)
    2731                 :            :                         return -EINVAL;
    2732         [ #  # ]:          0 :                 if (put_user(0, &_xfern->result))
    2733                 :            :                         return -EFAULT;
    2734         [ #  # ]:          0 :                 if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
    2735                 :            :                         return -EFAULT;
    2736                 :            : 
    2737                 :          0 :                 bufs = memdup_user(xfern.bufs,
    2738                 :          0 :                                    sizeof(void *) * runtime->channels);
    2739         [ #  # ]:          0 :                 if (IS_ERR(bufs))
    2740                 :          0 :                         return PTR_ERR(bufs);
    2741                 :          0 :                 result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
    2742                 :          0 :                 kfree(bufs);
    2743                 :          0 :                 __put_user(result, &_xfern->result);
    2744                 :          0 :                 return result < 0 ? result : 0;
    2745                 :            :         }
    2746                 :            :         case SNDRV_PCM_IOCTL_REWIND:
    2747                 :            :         {
    2748                 :            :                 snd_pcm_uframes_t frames;
    2749                 :            :                 snd_pcm_uframes_t __user *_frames = arg;
    2750                 :            :                 snd_pcm_sframes_t result;
    2751         [ #  # ]:          0 :                 if (get_user(frames, _frames))
    2752                 :            :                         return -EFAULT;
    2753         [ #  # ]:          0 :                 if (put_user(0, _frames))
    2754                 :            :                         return -EFAULT;
    2755                 :          0 :                 result = snd_pcm_capture_rewind(substream, frames);
    2756                 :          0 :                 __put_user(result, _frames);
    2757                 :          0 :                 return result < 0 ? result : 0;
    2758                 :            :         }
    2759                 :            :         case SNDRV_PCM_IOCTL_FORWARD:
    2760                 :            :         {
    2761                 :            :                 snd_pcm_uframes_t frames;
    2762                 :            :                 snd_pcm_uframes_t __user *_frames = arg;
    2763                 :            :                 snd_pcm_sframes_t result;
    2764         [ #  # ]:          0 :                 if (get_user(frames, _frames))
    2765                 :            :                         return -EFAULT;
    2766         [ #  # ]:          0 :                 if (put_user(0, _frames))
    2767                 :            :                         return -EFAULT;
    2768                 :          0 :                 result = snd_pcm_capture_forward(substream, frames);
    2769                 :          0 :                 __put_user(result, _frames);
    2770                 :          0 :                 return result < 0 ? result : 0;
    2771                 :            :         }
    2772                 :            :         }
    2773                 :          0 :         return snd_pcm_common_ioctl1(file, substream, cmd, arg);
    2774                 :            : }
    2775                 :            : 
    2776                 :          0 : static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
    2777                 :            :                                    unsigned long arg)
    2778                 :            : {
    2779                 :            :         struct snd_pcm_file *pcm_file;
    2780                 :            : 
    2781                 :          0 :         pcm_file = file->private_data;
    2782                 :            : 
    2783         [ #  # ]:          0 :         if (((cmd >> 8) & 0xff) != 'A')
    2784                 :            :                 return -ENOTTY;
    2785                 :            : 
    2786                 :          0 :         return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
    2787                 :            :                                        (void __user *)arg);
    2788                 :            : }
    2789                 :            : 
    2790                 :          0 : static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
    2791                 :            :                                   unsigned long arg)
    2792                 :            : {
    2793                 :            :         struct snd_pcm_file *pcm_file;
    2794                 :            : 
    2795                 :          0 :         pcm_file = file->private_data;
    2796                 :            : 
    2797         [ #  # ]:          0 :         if (((cmd >> 8) & 0xff) != 'A')
    2798                 :            :                 return -ENOTTY;
    2799                 :            : 
    2800                 :          0 :         return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
    2801                 :            :                                       (void __user *)arg);
    2802                 :            : }
    2803                 :            : 
    2804                 :          0 : int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
    2805                 :            :                          unsigned int cmd, void *arg)
    2806                 :            : {
    2807                 :            :         mm_segment_t fs;
    2808                 :            :         int result;
    2809                 :            :         
    2810                 :            :         fs = snd_enter_user();
    2811      [ #  #  # ]:          0 :         switch (substream->stream) {
    2812                 :            :         case SNDRV_PCM_STREAM_PLAYBACK:
    2813                 :          0 :                 result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
    2814                 :            :                                                  (void __user *)arg);
    2815                 :          0 :                 break;
    2816                 :            :         case SNDRV_PCM_STREAM_CAPTURE:
    2817                 :          0 :                 result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
    2818                 :            :                                                 (void __user *)arg);
    2819                 :          0 :                 break;
    2820                 :            :         default:
    2821                 :            :                 result = -EINVAL;
    2822                 :            :                 break;
    2823                 :            :         }
    2824                 :            :         snd_leave_user(fs);
    2825                 :          0 :         return result;
    2826                 :            : }
    2827                 :            : 
    2828                 :            : EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
    2829                 :            : 
    2830                 :          0 : static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
    2831                 :            :                             loff_t * offset)
    2832                 :            : {
    2833                 :            :         struct snd_pcm_file *pcm_file;
    2834                 :            :         struct snd_pcm_substream *substream;
    2835                 :          0 :         struct snd_pcm_runtime *runtime;
    2836                 :            :         snd_pcm_sframes_t result;
    2837                 :            : 
    2838                 :          0 :         pcm_file = file->private_data;
    2839                 :          0 :         substream = pcm_file->substream;
    2840 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
    2841                 :            :                 return -ENXIO;
    2842                 :          0 :         runtime = substream->runtime;
    2843         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    2844                 :            :                 return -EBADFD;
    2845         [ #  # ]:          0 :         if (!frame_aligned(runtime, count))
    2846                 :            :                 return -EINVAL;
    2847                 :          0 :         count = bytes_to_frames(runtime, count);
    2848                 :          0 :         result = snd_pcm_lib_read(substream, buf, count);
    2849         [ #  # ]:          0 :         if (result > 0)
    2850                 :            :                 result = frames_to_bytes(runtime, result);
    2851                 :          0 :         return result;
    2852                 :            : }
    2853                 :            : 
    2854                 :          0 : static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
    2855                 :            :                              size_t count, loff_t * offset)
    2856                 :            : {
    2857                 :            :         struct snd_pcm_file *pcm_file;
    2858                 :            :         struct snd_pcm_substream *substream;
    2859                 :          0 :         struct snd_pcm_runtime *runtime;
    2860                 :            :         snd_pcm_sframes_t result;
    2861                 :            : 
    2862                 :          0 :         pcm_file = file->private_data;
    2863                 :          0 :         substream = pcm_file->substream;
    2864 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
    2865                 :            :                 return -ENXIO;
    2866                 :          0 :         runtime = substream->runtime;
    2867         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    2868                 :            :                 return -EBADFD;
    2869         [ #  # ]:          0 :         if (!frame_aligned(runtime, count))
    2870                 :            :                 return -EINVAL;
    2871                 :          0 :         count = bytes_to_frames(runtime, count);
    2872                 :          0 :         result = snd_pcm_lib_write(substream, buf, count);
    2873         [ #  # ]:          0 :         if (result > 0)
    2874                 :            :                 result = frames_to_bytes(runtime, result);
    2875                 :          0 :         return result;
    2876                 :            : }
    2877                 :            : 
    2878                 :          0 : static ssize_t snd_pcm_aio_read(struct kiocb *iocb, const struct iovec *iov,
    2879                 :            :                              unsigned long nr_segs, loff_t pos)
    2880                 :            : 
    2881                 :            : {
    2882                 :            :         struct snd_pcm_file *pcm_file;
    2883                 :            :         struct snd_pcm_substream *substream;
    2884                 :          0 :         struct snd_pcm_runtime *runtime;
    2885                 :            :         snd_pcm_sframes_t result;
    2886                 :            :         unsigned long i;
    2887                 :            :         void __user **bufs;
    2888                 :            :         snd_pcm_uframes_t frames;
    2889                 :            : 
    2890                 :          0 :         pcm_file = iocb->ki_filp->private_data;
    2891                 :          0 :         substream = pcm_file->substream;
    2892 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
    2893                 :            :                 return -ENXIO;
    2894                 :          0 :         runtime = substream->runtime;
    2895         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    2896                 :            :                 return -EBADFD;
    2897 [ #  # ][ #  # ]:          0 :         if (nr_segs > 1024 || nr_segs != runtime->channels)
    2898                 :            :                 return -EINVAL;
    2899         [ #  # ]:          0 :         if (!frame_aligned(runtime, iov->iov_len))
    2900                 :            :                 return -EINVAL;
    2901                 :          0 :         frames = bytes_to_samples(runtime, iov->iov_len);
    2902                 :          0 :         bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL);
    2903         [ #  # ]:          0 :         if (bufs == NULL)
    2904                 :            :                 return -ENOMEM;
    2905         [ #  # ]:          0 :         for (i = 0; i < nr_segs; ++i)
    2906                 :          0 :                 bufs[i] = iov[i].iov_base;
    2907                 :          0 :         result = snd_pcm_lib_readv(substream, bufs, frames);
    2908         [ #  # ]:          0 :         if (result > 0)
    2909                 :            :                 result = frames_to_bytes(runtime, result);
    2910                 :          0 :         kfree(bufs);
    2911                 :          0 :         return result;
    2912                 :            : }
    2913                 :            : 
    2914                 :          0 : static ssize_t snd_pcm_aio_write(struct kiocb *iocb, const struct iovec *iov,
    2915                 :            :                               unsigned long nr_segs, loff_t pos)
    2916                 :            : {
    2917                 :            :         struct snd_pcm_file *pcm_file;
    2918                 :            :         struct snd_pcm_substream *substream;
    2919                 :          0 :         struct snd_pcm_runtime *runtime;
    2920                 :            :         snd_pcm_sframes_t result;
    2921                 :            :         unsigned long i;
    2922                 :            :         void __user **bufs;
    2923                 :            :         snd_pcm_uframes_t frames;
    2924                 :            : 
    2925                 :          0 :         pcm_file = iocb->ki_filp->private_data;
    2926                 :          0 :         substream = pcm_file->substream;
    2927 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
    2928                 :            :                 return -ENXIO;
    2929                 :          0 :         runtime = substream->runtime;
    2930         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    2931                 :            :                 return -EBADFD;
    2932 [ #  # ][ #  # ]:          0 :         if (nr_segs > 128 || nr_segs != runtime->channels ||
                 [ #  # ]
    2933                 :          0 :             !frame_aligned(runtime, iov->iov_len))
    2934                 :            :                 return -EINVAL;
    2935                 :          0 :         frames = bytes_to_samples(runtime, iov->iov_len);
    2936                 :          0 :         bufs = kmalloc(sizeof(void *) * nr_segs, GFP_KERNEL);
    2937         [ #  # ]:          0 :         if (bufs == NULL)
    2938                 :            :                 return -ENOMEM;
    2939         [ #  # ]:          0 :         for (i = 0; i < nr_segs; ++i)
    2940                 :          0 :                 bufs[i] = iov[i].iov_base;
    2941                 :          0 :         result = snd_pcm_lib_writev(substream, bufs, frames);
    2942         [ #  # ]:          0 :         if (result > 0)
    2943                 :            :                 result = frames_to_bytes(runtime, result);
    2944                 :          0 :         kfree(bufs);
    2945                 :          0 :         return result;
    2946                 :            : }
    2947                 :            : 
    2948                 :          0 : static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
    2949                 :            : {
    2950                 :            :         struct snd_pcm_file *pcm_file;
    2951                 :            :         struct snd_pcm_substream *substream;
    2952                 :            :         struct snd_pcm_runtime *runtime;
    2953                 :            :         unsigned int mask;
    2954                 :            :         snd_pcm_uframes_t avail;
    2955                 :            : 
    2956                 :          0 :         pcm_file = file->private_data;
    2957                 :            : 
    2958                 :          0 :         substream = pcm_file->substream;
    2959 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
    2960                 :            :                 return -ENXIO;
    2961                 :          0 :         runtime = substream->runtime;
    2962                 :            : 
    2963                 :          0 :         poll_wait(file, &runtime->sleep, wait);
    2964                 :            : 
    2965                 :            :         snd_pcm_stream_lock_irq(substream);
    2966                 :            :         avail = snd_pcm_playback_avail(runtime);
    2967      [ #  #  # ]:          0 :         switch (runtime->status->state) {
    2968                 :            :         case SNDRV_PCM_STATE_RUNNING:
    2969                 :            :         case SNDRV_PCM_STATE_PREPARED:
    2970                 :            :         case SNDRV_PCM_STATE_PAUSED:
    2971         [ #  # ]:          0 :                 if (avail >= runtime->control->avail_min) {
    2972                 :            :                         mask = POLLOUT | POLLWRNORM;
    2973                 :            :                         break;
    2974                 :            :                 }
    2975                 :            :                 /* Fall through */
    2976                 :            :         case SNDRV_PCM_STATE_DRAINING:
    2977                 :            :                 mask = 0;
    2978                 :          0 :                 break;
    2979                 :            :         default:
    2980                 :            :                 mask = POLLOUT | POLLWRNORM | POLLERR;
    2981                 :            :                 break;
    2982                 :            :         }
    2983                 :            :         snd_pcm_stream_unlock_irq(substream);
    2984                 :          0 :         return mask;
    2985                 :            : }
    2986                 :            : 
    2987                 :          0 : static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
    2988                 :            : {
    2989                 :            :         struct snd_pcm_file *pcm_file;
    2990                 :            :         struct snd_pcm_substream *substream;
    2991                 :            :         struct snd_pcm_runtime *runtime;
    2992                 :            :         unsigned int mask;
    2993                 :            :         snd_pcm_uframes_t avail;
    2994                 :            : 
    2995                 :          0 :         pcm_file = file->private_data;
    2996                 :            : 
    2997                 :          0 :         substream = pcm_file->substream;
    2998 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
    2999                 :            :                 return -ENXIO;
    3000                 :          0 :         runtime = substream->runtime;
    3001                 :            : 
    3002                 :          0 :         poll_wait(file, &runtime->sleep, wait);
    3003                 :            : 
    3004                 :            :         snd_pcm_stream_lock_irq(substream);
    3005                 :            :         avail = snd_pcm_capture_avail(runtime);
    3006      [ #  #  # ]:          0 :         switch (runtime->status->state) {
    3007                 :            :         case SNDRV_PCM_STATE_RUNNING:
    3008                 :            :         case SNDRV_PCM_STATE_PREPARED:
    3009                 :            :         case SNDRV_PCM_STATE_PAUSED:
    3010         [ #  # ]:          0 :                 if (avail >= runtime->control->avail_min) {
    3011                 :            :                         mask = POLLIN | POLLRDNORM;
    3012                 :            :                         break;
    3013                 :            :                 }
    3014                 :            :                 mask = 0;
    3015                 :          0 :                 break;
    3016                 :            :         case SNDRV_PCM_STATE_DRAINING:
    3017         [ #  # ]:          0 :                 if (avail > 0) {
    3018                 :            :                         mask = POLLIN | POLLRDNORM;
    3019                 :            :                         break;
    3020                 :            :                 }
    3021                 :            :                 /* Fall through */
    3022                 :            :         default:
    3023                 :            :                 mask = POLLIN | POLLRDNORM | POLLERR;
    3024                 :          0 :                 break;
    3025                 :            :         }
    3026                 :            :         snd_pcm_stream_unlock_irq(substream);
    3027                 :          0 :         return mask;
    3028                 :            : }
    3029                 :            : 
    3030                 :            : /*
    3031                 :            :  * mmap support
    3032                 :            :  */
    3033                 :            : 
    3034                 :            : /*
    3035                 :            :  * Only on coherent architectures, we can mmap the status and the control records
    3036                 :            :  * for effcient data transfer.  On others, we have to use HWSYNC ioctl...
    3037                 :            :  */
    3038                 :            : #if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
    3039                 :            : /*
    3040                 :            :  * mmap status record
    3041                 :            :  */
    3042                 :            : static int snd_pcm_mmap_status_fault(struct vm_area_struct *area,
    3043                 :            :                                                 struct vm_fault *vmf)
    3044                 :            : {
    3045                 :            :         struct snd_pcm_substream *substream = area->vm_private_data;
    3046                 :            :         struct snd_pcm_runtime *runtime;
    3047                 :            :         
    3048                 :            :         if (substream == NULL)
    3049                 :            :                 return VM_FAULT_SIGBUS;
    3050                 :            :         runtime = substream->runtime;
    3051                 :            :         vmf->page = virt_to_page(runtime->status);
    3052                 :            :         get_page(vmf->page);
    3053                 :            :         return 0;
    3054                 :            : }
    3055                 :            : 
    3056                 :            : static const struct vm_operations_struct snd_pcm_vm_ops_status =
    3057                 :            : {
    3058                 :            :         .fault =        snd_pcm_mmap_status_fault,
    3059                 :            : };
    3060                 :            : 
    3061                 :            : static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
    3062                 :            :                                struct vm_area_struct *area)
    3063                 :            : {
    3064                 :            :         long size;
    3065                 :            :         if (!(area->vm_flags & VM_READ))
    3066                 :            :                 return -EINVAL;
    3067                 :            :         size = area->vm_end - area->vm_start;
    3068                 :            :         if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
    3069                 :            :                 return -EINVAL;
    3070                 :            :         area->vm_ops = &snd_pcm_vm_ops_status;
    3071                 :            :         area->vm_private_data = substream;
    3072                 :            :         area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
    3073                 :            :         return 0;
    3074                 :            : }
    3075                 :            : 
    3076                 :            : /*
    3077                 :            :  * mmap control record
    3078                 :            :  */
    3079                 :            : static int snd_pcm_mmap_control_fault(struct vm_area_struct *area,
    3080                 :            :                                                 struct vm_fault *vmf)
    3081                 :            : {
    3082                 :            :         struct snd_pcm_substream *substream = area->vm_private_data;
    3083                 :            :         struct snd_pcm_runtime *runtime;
    3084                 :            :         
    3085                 :            :         if (substream == NULL)
    3086                 :            :                 return VM_FAULT_SIGBUS;
    3087                 :            :         runtime = substream->runtime;
    3088                 :            :         vmf->page = virt_to_page(runtime->control);
    3089                 :            :         get_page(vmf->page);
    3090                 :            :         return 0;
    3091                 :            : }
    3092                 :            : 
    3093                 :            : static const struct vm_operations_struct snd_pcm_vm_ops_control =
    3094                 :            : {
    3095                 :            :         .fault =        snd_pcm_mmap_control_fault,
    3096                 :            : };
    3097                 :            : 
    3098                 :            : static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
    3099                 :            :                                 struct vm_area_struct *area)
    3100                 :            : {
    3101                 :            :         long size;
    3102                 :            :         if (!(area->vm_flags & VM_READ))
    3103                 :            :                 return -EINVAL;
    3104                 :            :         size = area->vm_end - area->vm_start;
    3105                 :            :         if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
    3106                 :            :                 return -EINVAL;
    3107                 :            :         area->vm_ops = &snd_pcm_vm_ops_control;
    3108                 :            :         area->vm_private_data = substream;
    3109                 :            :         area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
    3110                 :            :         return 0;
    3111                 :            : }
    3112                 :            : #else /* ! coherent mmap */
    3113                 :            : /*
    3114                 :            :  * don't support mmap for status and control records.
    3115                 :            :  */
    3116                 :            : static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
    3117                 :            :                                struct vm_area_struct *area)
    3118                 :            : {
    3119                 :            :         return -ENXIO;
    3120                 :            : }
    3121                 :            : static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
    3122                 :            :                                 struct vm_area_struct *area)
    3123                 :            : {
    3124                 :            :         return -ENXIO;
    3125                 :            : }
    3126                 :            : #endif /* coherent mmap */
    3127                 :            : 
    3128                 :            : static inline struct page *
    3129                 :            : snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs)
    3130                 :            : {
    3131                 :          0 :         void *vaddr = substream->runtime->dma_area + ofs;
    3132                 :            : #if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
    3133                 :            :         if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
    3134                 :            :                 return virt_to_page(CAC_ADDR(vaddr));
    3135                 :            : #endif
    3136                 :            : #if defined(CONFIG_PPC32) && defined(CONFIG_NOT_COHERENT_CACHE)
    3137                 :            :         if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) {
    3138                 :            :                 dma_addr_t addr = substream->runtime->dma_addr + ofs;
    3139                 :            :                 addr -= get_dma_offset(substream->dma_buffer.dev.dev);
    3140                 :            :                 /* assume dma_handle set via pfn_to_phys() in
    3141                 :            :                  * mm/dma-noncoherent.c
    3142                 :            :                  */
    3143                 :            :                 return pfn_to_page(addr >> PAGE_SHIFT);
    3144                 :            :         }
    3145                 :            : #endif
    3146                 :          0 :         return virt_to_page(vaddr);
    3147                 :            : }
    3148                 :            : 
    3149                 :            : /*
    3150                 :            :  * fault callback for mmapping a RAM page
    3151                 :            :  */
    3152                 :          0 : static int snd_pcm_mmap_data_fault(struct vm_area_struct *area,
    3153                 :            :                                                 struct vm_fault *vmf)
    3154                 :            : {
    3155                 :          0 :         struct snd_pcm_substream *substream = area->vm_private_data;
    3156                 :            :         struct snd_pcm_runtime *runtime;
    3157                 :            :         unsigned long offset;
    3158                 :            :         struct page * page;
    3159                 :            :         size_t dma_bytes;
    3160                 :            :         
    3161         [ #  # ]:          0 :         if (substream == NULL)
    3162                 :            :                 return VM_FAULT_SIGBUS;
    3163                 :          0 :         runtime = substream->runtime;
    3164                 :          0 :         offset = vmf->pgoff << PAGE_SHIFT;
    3165                 :          0 :         dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
    3166         [ #  # ]:          0 :         if (offset > dma_bytes - PAGE_SIZE)
    3167                 :            :                 return VM_FAULT_SIGBUS;
    3168         [ #  # ]:          0 :         if (substream->ops->page)
    3169                 :          0 :                 page = substream->ops->page(substream, offset);
    3170                 :            :         else
    3171                 :            :                 page = snd_pcm_default_page_ops(substream, offset);
    3172         [ #  # ]:          0 :         if (!page)
    3173                 :            :                 return VM_FAULT_SIGBUS;
    3174                 :            :         get_page(page);
    3175                 :          0 :         vmf->page = page;
    3176                 :          0 :         return 0;
    3177                 :            : }
    3178                 :            : 
    3179                 :            : static const struct vm_operations_struct snd_pcm_vm_ops_data = {
    3180                 :            :         .open =         snd_pcm_mmap_data_open,
    3181                 :            :         .close =        snd_pcm_mmap_data_close,
    3182                 :            : };
    3183                 :            : 
    3184                 :            : static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = {
    3185                 :            :         .open =         snd_pcm_mmap_data_open,
    3186                 :            :         .close =        snd_pcm_mmap_data_close,
    3187                 :            :         .fault =        snd_pcm_mmap_data_fault,
    3188                 :            : };
    3189                 :            : 
    3190                 :            : #ifndef ARCH_HAS_DMA_MMAP_COHERENT
    3191                 :            : /* This should be defined / handled globally! */
    3192                 :            : #ifdef CONFIG_ARM
    3193                 :            : #define ARCH_HAS_DMA_MMAP_COHERENT
    3194                 :            : #endif
    3195                 :            : #endif
    3196                 :            : 
    3197                 :            : /*
    3198                 :            :  * mmap the DMA buffer on RAM
    3199                 :            :  */
    3200                 :          0 : int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
    3201                 :            :                              struct vm_area_struct *area)
    3202                 :            : {
    3203                 :          0 :         area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
    3204                 :            : #ifdef CONFIG_GENERIC_ALLOCATOR
    3205                 :            :         if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_IRAM) {
    3206                 :            :                 area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
    3207                 :            :                 return remap_pfn_range(area, area->vm_start,
    3208                 :            :                                 substream->dma_buffer.addr >> PAGE_SHIFT,
    3209                 :            :                                 area->vm_end - area->vm_start, area->vm_page_prot);
    3210                 :            :         }
    3211                 :            : #endif /* CONFIG_GENERIC_ALLOCATOR */
    3212                 :            : #ifdef ARCH_HAS_DMA_MMAP_COHERENT
    3213 [ #  # ][ #  # ]:          0 :         if (!substream->ops->page &&
    3214                 :          0 :             substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
    3215                 :          0 :                 return dma_mmap_coherent(substream->dma_buffer.dev.dev,
    3216                 :            :                                          area,
    3217                 :            :                                          substream->runtime->dma_area,
    3218                 :            :                                          substream->runtime->dma_addr,
    3219                 :            :                                          area->vm_end - area->vm_start);
    3220                 :            : #elif defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
    3221                 :            :         if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV &&
    3222                 :            :             !plat_device_is_coherent(substream->dma_buffer.dev.dev))
    3223                 :            :                 area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
    3224                 :            : #endif /* ARCH_HAS_DMA_MMAP_COHERENT */
    3225                 :            :         /* mmap with fault handler */
    3226                 :          0 :         area->vm_ops = &snd_pcm_vm_ops_data_fault;
    3227                 :          0 :         return 0;
    3228                 :            : }
    3229                 :            : EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
    3230                 :            : 
    3231                 :            : /*
    3232                 :            :  * mmap the DMA buffer on I/O memory area
    3233                 :            :  */
    3234                 :            : #if SNDRV_PCM_INFO_MMAP_IOMEM
    3235                 :            : int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
    3236                 :            :                            struct vm_area_struct *area)
    3237                 :            : {
    3238                 :            :         struct snd_pcm_runtime *runtime = substream->runtime;;
    3239                 :            : 
    3240                 :            :         area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
    3241                 :            :         return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
    3242                 :            : }
    3243                 :            : 
    3244                 :            : EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
    3245                 :            : #endif /* SNDRV_PCM_INFO_MMAP */
    3246                 :            : 
    3247                 :            : /*
    3248                 :            :  * mmap DMA buffer
    3249                 :            :  */
    3250                 :          0 : int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
    3251                 :            :                       struct vm_area_struct *area)
    3252                 :            : {
    3253                 :            :         struct snd_pcm_runtime *runtime;
    3254                 :            :         long size;
    3255                 :            :         unsigned long offset;
    3256                 :            :         size_t dma_bytes;
    3257                 :            :         int err;
    3258                 :            : 
    3259         [ #  # ]:          0 :         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    3260         [ #  # ]:          0 :                 if (!(area->vm_flags & (VM_WRITE|VM_READ)))
    3261                 :            :                         return -EINVAL;
    3262                 :            :         } else {
    3263         [ #  # ]:          0 :                 if (!(area->vm_flags & VM_READ))
    3264                 :            :                         return -EINVAL;
    3265                 :            :         }
    3266                 :          0 :         runtime = substream->runtime;
    3267         [ #  # ]:          0 :         if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
    3268                 :            :                 return -EBADFD;
    3269         [ #  # ]:          0 :         if (!(runtime->info & SNDRV_PCM_INFO_MMAP))
    3270                 :            :                 return -ENXIO;
    3271         [ #  # ]:          0 :         if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
    3272                 :            :             runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
    3273                 :            :                 return -EINVAL;
    3274                 :          0 :         size = area->vm_end - area->vm_start;
    3275                 :          0 :         offset = area->vm_pgoff << PAGE_SHIFT;
    3276                 :          0 :         dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
    3277         [ #  # ]:          0 :         if ((size_t)size > dma_bytes)
    3278                 :            :                 return -EINVAL;
    3279         [ #  # ]:          0 :         if (offset > dma_bytes - size)
    3280                 :            :                 return -EINVAL;
    3281                 :            : 
    3282                 :          0 :         area->vm_ops = &snd_pcm_vm_ops_data;
    3283                 :          0 :         area->vm_private_data = substream;
    3284         [ #  # ]:          0 :         if (substream->ops->mmap)
    3285                 :          0 :                 err = substream->ops->mmap(substream, area);
    3286                 :            :         else
    3287                 :          0 :                 err = snd_pcm_lib_default_mmap(substream, area);
    3288         [ #  # ]:          0 :         if (!err)
    3289                 :          0 :                 atomic_inc(&substream->mmap_count);
    3290                 :          0 :         return err;
    3291                 :            : }
    3292                 :            : 
    3293                 :            : EXPORT_SYMBOL(snd_pcm_mmap_data);
    3294                 :            : 
    3295                 :          0 : static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
    3296                 :            : {
    3297                 :            :         struct snd_pcm_file * pcm_file;
    3298                 :            :         struct snd_pcm_substream *substream;    
    3299                 :            :         unsigned long offset;
    3300                 :            :         
    3301                 :          0 :         pcm_file = file->private_data;
    3302                 :          0 :         substream = pcm_file->substream;
    3303 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
    3304                 :            :                 return -ENXIO;
    3305                 :            : 
    3306                 :          0 :         offset = area->vm_pgoff << PAGE_SHIFT;
    3307         [ #  # ]:          0 :         switch (offset) {
    3308                 :            :         case SNDRV_PCM_MMAP_OFFSET_STATUS:
    3309                 :            :                 if (pcm_file->no_compat_mmap)
    3310                 :            :                         return -ENXIO;
    3311                 :            :                 return snd_pcm_mmap_status(substream, file, area);
    3312                 :            :         case SNDRV_PCM_MMAP_OFFSET_CONTROL:
    3313                 :            :                 if (pcm_file->no_compat_mmap)
    3314                 :            :                         return -ENXIO;
    3315                 :            :                 return snd_pcm_mmap_control(substream, file, area);
    3316                 :            :         default:
    3317                 :          0 :                 return snd_pcm_mmap_data(substream, file, area);
    3318                 :            :         }
    3319                 :            :         return 0;
    3320                 :            : }
    3321                 :            : 
    3322                 :          0 : static int snd_pcm_fasync(int fd, struct file * file, int on)
    3323                 :            : {
    3324                 :            :         struct snd_pcm_file * pcm_file;
    3325                 :            :         struct snd_pcm_substream *substream;
    3326                 :            :         struct snd_pcm_runtime *runtime;
    3327                 :            : 
    3328                 :          0 :         pcm_file = file->private_data;
    3329                 :          0 :         substream = pcm_file->substream;
    3330 [ #  # ][ #  # ]:          0 :         if (PCM_RUNTIME_CHECK(substream))
                 [ #  # ]
    3331                 :            :                 return -ENXIO;
    3332                 :          0 :         runtime = substream->runtime;
    3333                 :          0 :         return fasync_helper(fd, file, on, &runtime->fasync);
    3334                 :            : }
    3335                 :            : 
    3336                 :            : /*
    3337                 :            :  * ioctl32 compat
    3338                 :            :  */
    3339                 :            : #ifdef CONFIG_COMPAT
    3340                 :            : #include "pcm_compat.c"
    3341                 :            : #else
    3342                 :            : #define snd_pcm_ioctl_compat    NULL
    3343                 :            : #endif
    3344                 :            : 
    3345                 :            : /*
    3346                 :            :  *  To be removed helpers to keep binary compatibility
    3347                 :            :  */
    3348                 :            : 
    3349                 :            : #ifdef CONFIG_SND_SUPPORT_OLD_API
    3350                 :            : #define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
    3351                 :            : #define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
    3352                 :            : 
    3353                 :          0 : static void snd_pcm_hw_convert_from_old_params(struct snd_pcm_hw_params *params,
    3354                 :            :                                                struct snd_pcm_hw_params_old *oparams)
    3355                 :            : {
    3356                 :            :         unsigned int i;
    3357                 :            : 
    3358                 :          0 :         memset(params, 0, sizeof(*params));
    3359                 :          0 :         params->flags = oparams->flags;
    3360         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
    3361                 :          0 :                 params->masks[i].bits[0] = oparams->masks[i];
    3362                 :          0 :         memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
    3363                 :          0 :         params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
    3364                 :          0 :         params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
    3365                 :          0 :         params->info = oparams->info;
    3366                 :          0 :         params->msbits = oparams->msbits;
    3367                 :          0 :         params->rate_num = oparams->rate_num;
    3368                 :          0 :         params->rate_den = oparams->rate_den;
    3369                 :          0 :         params->fifo_size = oparams->fifo_size;
    3370                 :          0 : }
    3371                 :            : 
    3372                 :          0 : static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *oparams,
    3373                 :            :                                              struct snd_pcm_hw_params *params)
    3374                 :            : {
    3375                 :            :         unsigned int i;
    3376                 :            : 
    3377                 :          0 :         memset(oparams, 0, sizeof(*oparams));
    3378                 :          0 :         oparams->flags = params->flags;
    3379         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
    3380                 :          0 :                 oparams->masks[i] = params->masks[i].bits[0];
    3381                 :          0 :         memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
    3382                 :          0 :         oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
    3383                 :          0 :         oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
    3384                 :          0 :         oparams->info = params->info;
    3385                 :          0 :         oparams->msbits = params->msbits;
    3386                 :          0 :         oparams->rate_num = params->rate_num;
    3387                 :          0 :         oparams->rate_den = params->rate_den;
    3388                 :          0 :         oparams->fifo_size = params->fifo_size;
    3389                 :          0 : }
    3390                 :            : 
    3391                 :          0 : static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
    3392                 :            :                                       struct snd_pcm_hw_params_old __user * _oparams)
    3393                 :            : {
    3394                 :            :         struct snd_pcm_hw_params *params;
    3395                 :            :         struct snd_pcm_hw_params_old *oparams = NULL;
    3396                 :            :         int err;
    3397                 :            : 
    3398                 :            :         params = kmalloc(sizeof(*params), GFP_KERNEL);
    3399         [ #  # ]:          0 :         if (!params)
    3400                 :            :                 return -ENOMEM;
    3401                 :            : 
    3402                 :          0 :         oparams = memdup_user(_oparams, sizeof(*oparams));
    3403         [ #  # ]:          0 :         if (IS_ERR(oparams)) {
    3404                 :            :                 err = PTR_ERR(oparams);
    3405                 :          0 :                 goto out;
    3406                 :            :         }
    3407                 :          0 :         snd_pcm_hw_convert_from_old_params(params, oparams);
    3408                 :          0 :         err = snd_pcm_hw_refine(substream, params);
    3409                 :          0 :         snd_pcm_hw_convert_to_old_params(oparams, params);
    3410         [ #  # ]:          0 :         if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
    3411         [ #  # ]:          0 :                 if (!err)
    3412                 :            :                         err = -EFAULT;
    3413                 :            :         }
    3414                 :            : 
    3415                 :          0 :         kfree(oparams);
    3416                 :            : out:
    3417                 :          0 :         kfree(params);
    3418                 :          0 :         return err;
    3419                 :            : }
    3420                 :            : 
    3421                 :          0 : static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
    3422                 :            :                                       struct snd_pcm_hw_params_old __user * _oparams)
    3423                 :            : {
    3424                 :            :         struct snd_pcm_hw_params *params;
    3425                 :            :         struct snd_pcm_hw_params_old *oparams = NULL;
    3426                 :            :         int err;
    3427                 :            : 
    3428                 :            :         params = kmalloc(sizeof(*params), GFP_KERNEL);
    3429         [ #  # ]:          0 :         if (!params)
    3430                 :            :                 return -ENOMEM;
    3431                 :            : 
    3432                 :          0 :         oparams = memdup_user(_oparams, sizeof(*oparams));
    3433         [ #  # ]:          0 :         if (IS_ERR(oparams)) {
    3434                 :            :                 err = PTR_ERR(oparams);
    3435                 :          0 :                 goto out;
    3436                 :            :         }
    3437                 :          0 :         snd_pcm_hw_convert_from_old_params(params, oparams);
    3438                 :          0 :         err = snd_pcm_hw_params(substream, params);
    3439                 :          0 :         snd_pcm_hw_convert_to_old_params(oparams, params);
    3440         [ #  # ]:          0 :         if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
    3441         [ #  # ]:          0 :                 if (!err)
    3442                 :            :                         err = -EFAULT;
    3443                 :            :         }
    3444                 :            : 
    3445                 :          0 :         kfree(oparams);
    3446                 :            : out:
    3447                 :          0 :         kfree(params);
    3448                 :          0 :         return err;
    3449                 :            : }
    3450                 :            : #endif /* CONFIG_SND_SUPPORT_OLD_API */
    3451                 :            : 
    3452                 :            : #ifndef CONFIG_MMU
    3453                 :            : static unsigned long snd_pcm_get_unmapped_area(struct file *file,
    3454                 :            :                                                unsigned long addr,
    3455                 :            :                                                unsigned long len,
    3456                 :            :                                                unsigned long pgoff,
    3457                 :            :                                                unsigned long flags)
    3458                 :            : {
    3459                 :            :         struct snd_pcm_file *pcm_file = file->private_data;
    3460                 :            :         struct snd_pcm_substream *substream = pcm_file->substream;
    3461                 :            :         struct snd_pcm_runtime *runtime = substream->runtime;
    3462                 :            :         unsigned long offset = pgoff << PAGE_SHIFT;
    3463                 :            : 
    3464                 :            :         switch (offset) {
    3465                 :            :         case SNDRV_PCM_MMAP_OFFSET_STATUS:
    3466                 :            :                 return (unsigned long)runtime->status;
    3467                 :            :         case SNDRV_PCM_MMAP_OFFSET_CONTROL:
    3468                 :            :                 return (unsigned long)runtime->control;
    3469                 :            :         default:
    3470                 :            :                 return (unsigned long)runtime->dma_area + offset;
    3471                 :            :         }
    3472                 :            : }
    3473                 :            : #else
    3474                 :            : # define snd_pcm_get_unmapped_area NULL
    3475                 :            : #endif
    3476                 :            : 
    3477                 :            : /*
    3478                 :            :  *  Register section
    3479                 :            :  */
    3480                 :            : 
    3481                 :            : const struct file_operations snd_pcm_f_ops[2] = {
    3482                 :            :         {
    3483                 :            :                 .owner =                THIS_MODULE,
    3484                 :            :                 .write =                snd_pcm_write,
    3485                 :            :                 .aio_write =            snd_pcm_aio_write,
    3486                 :            :                 .open =                 snd_pcm_playback_open,
    3487                 :            :                 .release =              snd_pcm_release,
    3488                 :            :                 .llseek =               no_llseek,
    3489                 :            :                 .poll =                 snd_pcm_playback_poll,
    3490                 :            :                 .unlocked_ioctl =       snd_pcm_playback_ioctl,
    3491                 :            :                 .compat_ioctl =         snd_pcm_ioctl_compat,
    3492                 :            :                 .mmap =                 snd_pcm_mmap,
    3493                 :            :                 .fasync =               snd_pcm_fasync,
    3494                 :            :                 .get_unmapped_area =    snd_pcm_get_unmapped_area,
    3495                 :            :         },
    3496                 :            :         {
    3497                 :            :                 .owner =                THIS_MODULE,
    3498                 :            :                 .read =                 snd_pcm_read,
    3499                 :            :                 .aio_read =             snd_pcm_aio_read,
    3500                 :            :                 .open =                 snd_pcm_capture_open,
    3501                 :            :                 .release =              snd_pcm_release,
    3502                 :            :                 .llseek =               no_llseek,
    3503                 :            :                 .poll =                 snd_pcm_capture_poll,
    3504                 :            :                 .unlocked_ioctl =       snd_pcm_capture_ioctl,
    3505                 :            :                 .compat_ioctl =         snd_pcm_ioctl_compat,
    3506                 :            :                 .mmap =                 snd_pcm_mmap,
    3507                 :            :                 .fasync =               snd_pcm_fasync,
    3508                 :            :                 .get_unmapped_area =    snd_pcm_get_unmapped_area,
    3509                 :            :         }
    3510                 :            : };

Generated by: LCOV version 1.9