linux/sound/usb/clock.c
<<
>>
Prefs
   1/*
   2 *   Clock domain and sample rate management functions
   3 *
   4 *   This program is free software; you can redistribute it and/or modify
   5 *   it under the terms of the GNU General Public License as published by
   6 *   the Free Software Foundation; either version 2 of the License, or
   7 *   (at your option) any later version.
   8 *
   9 *   This program is distributed in the hope that it will be useful,
  10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 *   GNU General Public License for more details.
  13 *
  14 *   You should have received a copy of the GNU General Public License
  15 *   along with this program; if not, write to the Free Software
  16 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  17 *
  18 */
  19
  20#include <linux/bitops.h>
  21#include <linux/init.h>
  22#include <linux/string.h>
  23#include <linux/usb.h>
  24#include <linux/usb/audio.h>
  25#include <linux/usb/audio-v2.h>
  26
  27#include <sound/core.h>
  28#include <sound/info.h>
  29#include <sound/pcm.h>
  30
  31#include "usbaudio.h"
  32#include "card.h"
  33#include "helper.h"
  34#include "clock.h"
  35#include "quirks.h"
  36
  37static struct uac_clock_source_descriptor *
  38        snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
  39                                  int clock_id)
  40{
  41        struct uac_clock_source_descriptor *cs = NULL;
  42
  43        while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
  44                                             ctrl_iface->extralen,
  45                                             cs, UAC2_CLOCK_SOURCE))) {
  46                if (cs->bClockID == clock_id)
  47                        return cs;
  48        }
  49
  50        return NULL;
  51}
  52
  53static struct uac_clock_selector_descriptor *
  54        snd_usb_find_clock_selector(struct usb_host_interface *ctrl_iface,
  55                                    int clock_id)
  56{
  57        struct uac_clock_selector_descriptor *cs = NULL;
  58
  59        while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
  60                                             ctrl_iface->extralen,
  61                                             cs, UAC2_CLOCK_SELECTOR))) {
  62                if (cs->bClockID == clock_id)
  63                        return cs;
  64        }
  65
  66        return NULL;
  67}
  68
  69static struct uac_clock_multiplier_descriptor *
  70        snd_usb_find_clock_multiplier(struct usb_host_interface *ctrl_iface,
  71                                      int clock_id)
  72{
  73        struct uac_clock_multiplier_descriptor *cs = NULL;
  74
  75        while ((cs = snd_usb_find_csint_desc(ctrl_iface->extra,
  76                                             ctrl_iface->extralen,
  77                                             cs, UAC2_CLOCK_MULTIPLIER))) {
  78                if (cs->bClockID == clock_id)
  79                        return cs;
  80        }
  81
  82        return NULL;
  83}
  84
  85static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
  86{
  87        unsigned char buf;
  88        int ret;
  89
  90        ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
  91                              UAC2_CS_CUR,
  92                              USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
  93                              UAC2_CX_CLOCK_SELECTOR << 8,
  94                              snd_usb_ctrl_intf(chip) | (selector_id << 8),
  95                              &buf, sizeof(buf));
  96
  97        if (ret < 0)
  98                return ret;
  99
 100        return buf;
 101}
 102
 103static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id,
 104                                        unsigned char pin)
 105{
 106        int ret;
 107
 108        ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
 109                              UAC2_CS_CUR,
 110                              USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
 111                              UAC2_CX_CLOCK_SELECTOR << 8,
 112                              snd_usb_ctrl_intf(chip) | (selector_id << 8),
 113                              &pin, sizeof(pin));
 114        if (ret < 0)
 115                return ret;
 116
 117        if (ret != sizeof(pin)) {
 118                snd_printk(KERN_ERR
 119                        "usb-audio:%d: setting selector (id %d) unexpected length %d\n",
 120                        chip->dev->devnum, selector_id, ret);
 121                return -EINVAL;
 122        }
 123
 124        ret = uac_clock_selector_get_val(chip, selector_id);
 125        if (ret < 0)
 126                return ret;
 127
 128        if (ret != pin) {
 129                snd_printk(KERN_ERR
 130                        "usb-audio:%d: setting selector (id %d) to %x failed (current: %d)\n",
 131                        chip->dev->devnum, selector_id, pin, ret);
 132                return -EINVAL;
 133        }
 134
 135        return ret;
 136}
 137
 138static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
 139{
 140        int err;
 141        unsigned char data;
 142        struct usb_device *dev = chip->dev;
 143        struct uac_clock_source_descriptor *cs_desc =
 144                snd_usb_find_clock_source(chip->ctrl_intf, source_id);
 145
 146        if (!cs_desc)
 147                return 0;
 148
 149        /* If a clock source can't tell us whether it's valid, we assume it is */
 150        if (!uac2_control_is_readable(cs_desc->bmControls,
 151                                      UAC2_CS_CONTROL_CLOCK_VALID - 1))
 152                return 1;
 153
 154        err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
 155                              USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
 156                              UAC2_CS_CONTROL_CLOCK_VALID << 8,
 157                              snd_usb_ctrl_intf(chip) | (source_id << 8),
 158                              &data, sizeof(data));
 159
 160        if (err < 0) {
 161                snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n",
 162                           __func__, source_id);
 163                return 0;
 164        }
 165
 166        return !!data;
 167}
 168
 169static int __uac_clock_find_source(struct snd_usb_audio *chip,
 170                                   int entity_id, unsigned long *visited,
 171                                   bool validate)
 172{
 173        struct uac_clock_source_descriptor *source;
 174        struct uac_clock_selector_descriptor *selector;
 175        struct uac_clock_multiplier_descriptor *multiplier;
 176
 177        entity_id &= 0xff;
 178
 179        if (test_and_set_bit(entity_id, visited)) {
 180                snd_printk(KERN_WARNING
 181                        "%s(): recursive clock topology detected, id %d.\n",
 182                        __func__, entity_id);
 183                return -EINVAL;
 184        }
 185
 186        /* first, see if the ID we're looking for is a clock source already */
 187        source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
 188        if (source) {
 189                entity_id = source->bClockID;
 190                if (validate && !uac_clock_source_is_valid(chip, entity_id)) {
 191                        snd_printk(KERN_ERR "usb-audio:%d: clock source %d is not valid, cannot use\n",
 192                                   chip->dev->devnum, entity_id);
 193                        return -ENXIO;
 194                }
 195                return entity_id;
 196        }
 197
 198        selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id);
 199        if (selector) {
 200                int ret, i, cur;
 201
 202                /* the entity ID we are looking for is a selector.
 203                 * find out what it currently selects */
 204                ret = uac_clock_selector_get_val(chip, selector->bClockID);
 205                if (ret < 0)
 206                        return ret;
 207
 208                /* Selector values are one-based */
 209
 210                if (ret > selector->bNrInPins || ret < 1) {
 211                        snd_printk(KERN_ERR
 212                                "%s(): selector reported illegal value, id %d, ret %d\n",
 213                                __func__, selector->bClockID, ret);
 214
 215                        return -EINVAL;
 216                }
 217
 218                cur = ret;
 219                ret = __uac_clock_find_source(chip, selector->baCSourceID[ret - 1],
 220                                               visited, validate);
 221                if (!validate || ret > 0 || !chip->autoclock)
 222                        return ret;
 223
 224                /* The current clock source is invalid, try others. */
 225                for (i = 1; i <= selector->bNrInPins; i++) {
 226                        int err;
 227
 228                        if (i == cur)
 229                                continue;
 230
 231                        ret = __uac_clock_find_source(chip, selector->baCSourceID[i - 1],
 232                                visited, true);
 233                        if (ret < 0)
 234                                continue;
 235
 236                        err = uac_clock_selector_set_val(chip, entity_id, i);
 237                        if (err < 0)
 238                                continue;
 239
 240                        snd_printk(KERN_INFO
 241                                "usb-audio:%d: found and selected valid clock source %d\n",
 242                                chip->dev->devnum, ret);
 243                        return ret;
 244                }
 245
 246                return -ENXIO;
 247        }
 248
 249        /* FIXME: multipliers only act as pass-thru element for now */
 250        multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id);
 251        if (multiplier)
 252                return __uac_clock_find_source(chip, multiplier->bCSourceID,
 253                                                visited, validate);
 254
 255        return -EINVAL;
 256}
 257
 258/*
 259 * For all kinds of sample rate settings and other device queries,
 260 * the clock source (end-leaf) must be used. However, clock selectors,
 261 * clock multipliers and sample rate converters may be specified as
 262 * clock source input to terminal. This functions walks the clock path
 263 * to its end and tries to find the source.
 264 *
 265 * The 'visited' bitfield is used internally to detect recursive loops.
 266 *
 267 * Returns the clock source UnitID (>=0) on success, or an error.
 268 */
 269int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id,
 270                              bool validate)
 271{
 272        DECLARE_BITMAP(visited, 256);
 273        memset(visited, 0, sizeof(visited));
 274        return __uac_clock_find_source(chip, entity_id, visited, validate);
 275}
 276
 277static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
 278                              struct usb_host_interface *alts,
 279                              struct audioformat *fmt, int rate)
 280{
 281        struct usb_device *dev = chip->dev;
 282        unsigned int ep;
 283        unsigned char data[3];
 284        int err, crate;
 285
 286        ep = get_endpoint(alts, 0)->bEndpointAddress;
 287
 288        /* if endpoint doesn't have sampling rate control, bail out */
 289        if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE))
 290                return 0;
 291
 292        data[0] = rate;
 293        data[1] = rate >> 8;
 294        data[2] = rate >> 16;
 295        if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
 296                                   USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 297                                   UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
 298                                   data, sizeof(data))) < 0) {
 299                snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
 300                           dev->devnum, iface, fmt->altsetting, rate, ep);
 301                return err;
 302        }
 303
 304        if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
 305                                   USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
 306                                   UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
 307                                   data, sizeof(data))) < 0) {
 308                snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
 309                           dev->devnum, iface, fmt->altsetting, ep);
 310                return 0; /* some devices don't support reading */
 311        }
 312
 313        crate = data[0] | (data[1] << 8) | (data[2] << 16);
 314        if (crate != rate) {
 315                snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
 316                // runtime->rate = crate;
 317        }
 318
 319        return 0;
 320}
 321
 322static int get_sample_rate_v2(struct snd_usb_audio *chip, int iface,
 323                              int altsetting, int clock)
 324{
 325        struct usb_device *dev = chip->dev;
 326        __le32 data;
 327        int err;
 328
 329        err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
 330                              USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
 331                              UAC2_CS_CONTROL_SAM_FREQ << 8,
 332                              snd_usb_ctrl_intf(chip) | (clock << 8),
 333                              &data, sizeof(data));
 334        if (err < 0) {
 335                snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2): err %d\n",
 336                           dev->devnum, iface, altsetting, err);
 337                return 0;
 338        }
 339
 340        return le32_to_cpu(data);
 341}
 342
 343static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
 344                              struct usb_host_interface *alts,
 345                              struct audioformat *fmt, int rate)
 346{
 347        struct usb_device *dev = chip->dev;
 348        __le32 data;
 349        int err, cur_rate, prev_rate;
 350        int clock;
 351        bool writeable;
 352        struct uac_clock_source_descriptor *cs_desc;
 353
 354        clock = snd_usb_clock_find_source(chip, fmt->clock, true);
 355        if (clock < 0)
 356                return clock;
 357
 358        prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
 359        if (prev_rate == rate)
 360                return 0;
 361
 362        cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
 363        writeable = uac2_control_is_writeable(cs_desc->bmControls, UAC2_CS_CONTROL_SAM_FREQ - 1);
 364        if (writeable) {
 365                data = cpu_to_le32(rate);
 366                err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
 367                                      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
 368                                      UAC2_CS_CONTROL_SAM_FREQ << 8,
 369                                      snd_usb_ctrl_intf(chip) | (clock << 8),
 370                                      &data, sizeof(data));
 371                if (err < 0) {
 372                        snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2): err %d\n",
 373                                   dev->devnum, iface, fmt->altsetting, rate, err);
 374                        return err;
 375                }
 376
 377                cur_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
 378        } else {
 379                cur_rate = prev_rate;
 380        }
 381
 382        if (cur_rate != rate) {
 383                if (!writeable) {
 384                        snd_printk(KERN_WARNING
 385                                   "%d:%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
 386                                   dev->devnum, iface, fmt->altsetting, rate, cur_rate);
 387                        return -ENXIO;
 388                }
 389                snd_printd(KERN_WARNING
 390                           "current rate %d is different from the runtime rate %d\n",
 391                           cur_rate, rate);
 392        }
 393
 394        /* Some devices doesn't respond to sample rate changes while the
 395         * interface is active. */
 396        if (rate != prev_rate) {
 397                usb_set_interface(dev, iface, 0);
 398                snd_usb_set_interface_quirk(dev);
 399                usb_set_interface(dev, iface, fmt->altsetting);
 400                snd_usb_set_interface_quirk(dev);
 401        }
 402
 403        return 0;
 404}
 405
 406int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
 407                             struct usb_host_interface *alts,
 408                             struct audioformat *fmt, int rate)
 409{
 410        struct usb_interface_descriptor *altsd = get_iface_desc(alts);
 411
 412        switch (altsd->bInterfaceProtocol) {
 413        case UAC_VERSION_1:
 414        default:
 415                return set_sample_rate_v1(chip, iface, alts, fmt, rate);
 416
 417        case UAC_VERSION_2:
 418                return set_sample_rate_v2(chip, iface, alts, fmt, rate);
 419        }
 420}
 421
 422