smb3: allow uid and gid owners to be set on create with idsfromsid mount option
[linux-2.6-microblaze.git] / sound / usb / endpoint.c
index 4a9a2f6..9bea7d3 100644 (file)
@@ -124,12 +124,12 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep)
 
 /*
  * For streaming based on information derived from sync endpoints,
- * prepare_outbound_urb_sizes() will call next_packet_size() to
+ * prepare_outbound_urb_sizes() will call slave_next_packet_size() to
  * determine the number of samples to be sent in the next packet.
  *
- * For implicit feedback, next_packet_size() is unused.
+ * For implicit feedback, slave_next_packet_size() is unused.
  */
-int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep)
 {
        unsigned long flags;
        int ret;
@@ -146,6 +146,29 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
        return ret;
 }
 
+/*
+ * For adaptive and synchronous endpoints, prepare_outbound_urb_sizes()
+ * will call next_packet_size() to determine the number of samples to be
+ * sent in the next packet.
+ */
+int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
+{
+       int ret;
+
+       if (ep->fill_max)
+               return ep->maxframesize;
+
+       ep->sample_accum += ep->sample_rem;
+       if (ep->sample_accum >= ep->fps) {
+               ep->sample_accum -= ep->fps;
+               ret = ep->framesize[1];
+       } else {
+               ret = ep->framesize[0];
+       }
+
+       return ret;
+}
+
 static void retire_outbound_urb(struct snd_usb_endpoint *ep,
                                struct snd_urb_ctx *urb_ctx)
 {
@@ -190,6 +213,8 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep,
 
                if (ctx->packet_size[i])
                        counts = ctx->packet_size[i];
+               else if (ep->sync_master)
+                       counts = snd_usb_endpoint_slave_next_packet_size(ep);
                else
                        counts = snd_usb_endpoint_next_packet_size(ep);
 
@@ -321,17 +346,17 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
                        ep->next_packet_read_pos %= MAX_URBS;
 
                        /* take URB out of FIFO */
-                       if (!list_empty(&ep->ready_playback_urbs))
+                       if (!list_empty(&ep->ready_playback_urbs)) {
                                ctx = list_first_entry(&ep->ready_playback_urbs,
                                               struct snd_urb_ctx, ready_list);
+                               list_del_init(&ctx->ready_list);
+                       }
                }
                spin_unlock_irqrestore(&ep->lock, flags);
 
                if (ctx == NULL)
                        return;
 
-               list_del_init(&ctx->ready_list);
-
                /* copy over the length information */
                for (i = 0; i < packet->packets; i++)
                        ctx->packet_size[i] = packet->packet_size[i];
@@ -497,6 +522,8 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
 
        list_add_tail(&ep->list, &chip->ep_list);
 
+       ep->is_implicit_feedback = 0;
+
 __exit_unlock:
        mutex_unlock(&chip->mutex);
 
@@ -596,6 +623,178 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
        ep->nurbs = 0;
 }
 
+/*
+ * Check data endpoint for format differences
+ */
+static bool check_ep_params(struct snd_usb_endpoint *ep,
+                             snd_pcm_format_t pcm_format,
+                             unsigned int channels,
+                             unsigned int period_bytes,
+                             unsigned int frames_per_period,
+                             unsigned int periods_per_buffer,
+                             struct audioformat *fmt,
+                             struct snd_usb_endpoint *sync_ep)
+{
+       unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb;
+       unsigned int max_packs_per_period, urbs_per_period, urb_packs;
+       unsigned int max_urbs;
+       int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels;
+       int tx_length_quirk = (ep->chip->tx_length_quirk &&
+                              usb_pipeout(ep->pipe));
+       bool ret = 1;
+
+       if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
+               /*
+                * When operating in DSD DOP mode, the size of a sample frame
+                * in hardware differs from the actual physical format width
+                * because we need to make room for the DOP markers.
+                */
+               frame_bits += channels << 3;
+       }
+
+       ret = ret && (ep->datainterval == fmt->datainterval);
+       ret = ret && (ep->stride == frame_bits >> 3);
+
+       switch (pcm_format) {
+       case SNDRV_PCM_FORMAT_U8:
+               ret = ret && (ep->silence_value == 0x80);
+               break;
+       case SNDRV_PCM_FORMAT_DSD_U8:
+       case SNDRV_PCM_FORMAT_DSD_U16_LE:
+       case SNDRV_PCM_FORMAT_DSD_U32_LE:
+       case SNDRV_PCM_FORMAT_DSD_U16_BE:
+       case SNDRV_PCM_FORMAT_DSD_U32_BE:
+               ret = ret && (ep->silence_value == 0x69);
+               break;
+       default:
+               ret = ret && (ep->silence_value == 0);
+       }
+
+       /* assume max. frequency is 50% higher than nominal */
+       ret = ret && (ep->freqmax == ep->freqn + (ep->freqn >> 1));
+       /* Round up freqmax to nearest integer in order to calculate maximum
+        * packet size, which must represent a whole number of frames.
+        * This is accomplished by adding 0x0.ffff before converting the
+        * Q16.16 format into integer.
+        * In order to accurately calculate the maximum packet size when
+        * the data interval is more than 1 (i.e. ep->datainterval > 0),
+        * multiply by the data interval prior to rounding. For instance,
+        * a freqmax of 41 kHz will result in a max packet size of 6 (5.125)
+        * frames with a data interval of 1, but 11 (10.25) frames with a
+        * data interval of 2.
+        * (ep->freqmax << ep->datainterval overflows at 8.192 MHz for the
+        * maximum datainterval value of 3, at USB full speed, higher for
+        * USB high speed, noting that ep->freqmax is in units of
+        * frames per packet in Q16.16 format.)
+        */
+       maxsize = (((ep->freqmax << ep->datainterval) + 0xffff) >> 16) *
+                        (frame_bits >> 3);
+       if (tx_length_quirk)
+               maxsize += sizeof(__le32); /* Space for length descriptor */
+       /* but wMaxPacketSize might reduce this */
+       if (ep->maxpacksize && ep->maxpacksize < maxsize) {
+               /* whatever fits into a max. size packet */
+               unsigned int data_maxsize = maxsize = ep->maxpacksize;
+
+               if (tx_length_quirk)
+                       /* Need to remove the length descriptor to calc freq */
+                       data_maxsize -= sizeof(__le32);
+               ret = ret && (ep->freqmax == (data_maxsize / (frame_bits >> 3))
+                               << (16 - ep->datainterval));
+       }
+
+       if (ep->fill_max)
+               ret = ret && (ep->curpacksize == ep->maxpacksize);
+       else
+               ret = ret && (ep->curpacksize == maxsize);
+
+       if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) {
+               packs_per_ms = 8 >> ep->datainterval;
+               max_packs_per_urb = MAX_PACKS_HS;
+       } else {
+               packs_per_ms = 1;
+               max_packs_per_urb = MAX_PACKS;
+       }
+       if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
+               max_packs_per_urb = min(max_packs_per_urb,
+                                       1U << sync_ep->syncinterval);
+       max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval);
+
+       /*
+        * Capture endpoints need to use small URBs because there's no way
+        * to tell in advance where the next period will end, and we don't
+        * want the next URB to complete much after the period ends.
+        *
+        * Playback endpoints with implicit sync much use the same parameters
+        * as their corresponding capture endpoint.
+        */
+       if (usb_pipein(ep->pipe) ||
+                       snd_usb_endpoint_implicit_feedback_sink(ep)) {
+
+               urb_packs = packs_per_ms;
+               /*
+                * Wireless devices can poll at a max rate of once per 4ms.
+                * For dataintervals less than 5, increase the packet count to
+                * allow the host controller to use bursting to fill in the
+                * gaps.
+                */
+               if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_WIRELESS) {
+                       int interval = ep->datainterval;
+
+                       while (interval < 5) {
+                               urb_packs <<= 1;
+                               ++interval;
+                       }
+               }
+               /* make capture URBs <= 1 ms and smaller than a period */
+               urb_packs = min(max_packs_per_urb, urb_packs);
+               while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+                       urb_packs >>= 1;
+               ret = ret && (ep->nurbs == MAX_URBS);
+
+       /*
+        * Playback endpoints without implicit sync are adjusted so that
+        * a period fits as evenly as possible in the smallest number of
+        * URBs.  The total number of URBs is adjusted to the size of the
+        * ALSA buffer, subject to the MAX_URBS and MAX_QUEUE limits.
+        */
+       } else {
+               /* determine how small a packet can be */
+               minsize = (ep->freqn >> (16 - ep->datainterval)) *
+                               (frame_bits >> 3);
+               /* with sync from device, assume it can be 12% lower */
+               if (sync_ep)
+                       minsize -= minsize >> 3;
+               minsize = max(minsize, 1u);
+
+               /* how many packets will contain an entire ALSA period? */
+               max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize);
+
+               /* how many URBs will contain a period? */
+               urbs_per_period = DIV_ROUND_UP(max_packs_per_period,
+                               max_packs_per_urb);
+               /* how many packets are needed in each URB? */
+               urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period);
+
+               /* limit the number of frames in a single URB */
+               ret = ret && (ep->max_urb_frames ==
+                       DIV_ROUND_UP(frames_per_period, urbs_per_period));
+
+               /* try to use enough URBs to contain an entire ALSA buffer */
+               max_urbs = min((unsigned) MAX_URBS,
+                               MAX_QUEUE * packs_per_ms / urb_packs);
+               ret = ret && (ep->nurbs == min(max_urbs,
+                               urbs_per_period * periods_per_buffer));
+       }
+
+       ret = ret && (ep->datainterval == fmt->datainterval);
+       ret = ret && (ep->maxpacksize == fmt->maxpacksize);
+       ret = ret &&
+               (ep->fill_max == !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX));
+
+       return ret;
+}
+
 /*
  * configure a data endpoint
  */
@@ -861,10 +1060,23 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
        int err;
 
        if (ep->use_count != 0) {
-               usb_audio_warn(ep->chip,
-                        "Unable to change format on ep #%x: already in use\n",
-                        ep->ep_num);
-               return -EBUSY;
+               bool check = ep->is_implicit_feedback &&
+                       check_ep_params(ep, pcm_format,
+                                            channels, period_bytes,
+                                            period_frames, buffer_periods,
+                                            fmt, sync_ep);
+
+               if (!check) {
+                       usb_audio_warn(ep->chip,
+                               "Unable to change format on ep #%x: already in use\n",
+                               ep->ep_num);
+                       return -EBUSY;
+               }
+
+               usb_audio_dbg(ep->chip,
+                             "Ep #%x already in use as implicit feedback but format not changed\n",
+                             ep->ep_num);
+               return 0;
        }
 
        /* release old buffers, if any */
@@ -874,10 +1086,17 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
        ep->maxpacksize = fmt->maxpacksize;
        ep->fill_max = !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX);
 
-       if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL)
+       if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) {
                ep->freqn = get_usb_full_speed_rate(rate);
-       else
+               ep->fps = 1000;
+       } else {
                ep->freqn = get_usb_high_speed_rate(rate);
+               ep->fps = 8000;
+       }
+
+       ep->sample_rem = rate % ep->fps;
+       ep->framesize[0] = rate / ep->fps;
+       ep->framesize[1] = (rate + (ep->fps - 1)) / ep->fps;
 
        /* calculate the frequency in 16.16 format */
        ep->freqm = ep->freqn;
@@ -936,6 +1155,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
        ep->active_mask = 0;
        ep->unlink_mask = 0;
        ep->phase = 0;
+       ep->sample_accum = 0;
 
        snd_usb_endpoint_start_quirk(ep);