mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-16 22:10:24 +00:00
Merge branch 'topic/usb-audio' into for-linus
This commit is contained in:
commit
8c941de176
@ -121,6 +121,7 @@ struct audioformat {
|
|||||||
unsigned char attributes; /* corresponding attributes of cs endpoint */
|
unsigned char attributes; /* corresponding attributes of cs endpoint */
|
||||||
unsigned char endpoint; /* endpoint */
|
unsigned char endpoint; /* endpoint */
|
||||||
unsigned char ep_attr; /* endpoint attributes */
|
unsigned char ep_attr; /* endpoint attributes */
|
||||||
|
unsigned char datainterval; /* log_2 of data packet interval */
|
||||||
unsigned int maxpacksize; /* max. packet size */
|
unsigned int maxpacksize; /* max. packet size */
|
||||||
unsigned int rates; /* rate bitmasks */
|
unsigned int rates; /* rate bitmasks */
|
||||||
unsigned int rate_min, rate_max; /* min/max rates */
|
unsigned int rate_min, rate_max; /* min/max rates */
|
||||||
@ -170,7 +171,6 @@ struct snd_usb_substream {
|
|||||||
unsigned int curframesize; /* current packet size in frames (for capture) */
|
unsigned int curframesize; /* current packet size in frames (for capture) */
|
||||||
unsigned int fill_max: 1; /* fill max packet size always */
|
unsigned int fill_max: 1; /* fill max packet size always */
|
||||||
unsigned int fmt_type; /* USB audio format type (1-3) */
|
unsigned int fmt_type; /* USB audio format type (1-3) */
|
||||||
unsigned int packs_per_ms; /* packets per millisecond (for playback) */
|
|
||||||
|
|
||||||
unsigned int running: 1; /* running status */
|
unsigned int running: 1; /* running status */
|
||||||
|
|
||||||
@ -607,9 +607,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* finish at the frame boundary at/after the period boundary */
|
if (period_elapsed) /* finish at the period boundary */
|
||||||
if (period_elapsed &&
|
|
||||||
(i & (subs->packs_per_ms - 1)) == subs->packs_per_ms - 1)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (subs->hwptr_done + offs > runtime->buffer_size) {
|
if (subs->hwptr_done + offs > runtime->buffer_size) {
|
||||||
@ -1067,7 +1065,6 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
|
|||||||
packs_per_ms = 8 >> subs->datainterval;
|
packs_per_ms = 8 >> subs->datainterval;
|
||||||
else
|
else
|
||||||
packs_per_ms = 1;
|
packs_per_ms = 1;
|
||||||
subs->packs_per_ms = packs_per_ms;
|
|
||||||
|
|
||||||
if (is_playback) {
|
if (is_playback) {
|
||||||
urb_packs = max(nrpacks, 1);
|
urb_packs = max(nrpacks, 1);
|
||||||
@ -1087,18 +1084,17 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
|
|||||||
minsize -= minsize >> 3;
|
minsize -= minsize >> 3;
|
||||||
minsize = max(minsize, 1u);
|
minsize = max(minsize, 1u);
|
||||||
total_packs = (period_bytes + minsize - 1) / minsize;
|
total_packs = (period_bytes + minsize - 1) / minsize;
|
||||||
/* round up to multiple of packs_per_ms */
|
|
||||||
total_packs = (total_packs + packs_per_ms - 1)
|
|
||||||
& ~(packs_per_ms - 1);
|
|
||||||
/* we need at least two URBs for queueing */
|
/* we need at least two URBs for queueing */
|
||||||
if (total_packs < 2 * packs_per_ms) {
|
if (total_packs < 2) {
|
||||||
total_packs = 2 * packs_per_ms;
|
total_packs = 2;
|
||||||
} else {
|
} else {
|
||||||
/* and we don't want too long a queue either */
|
/* and we don't want too long a queue either */
|
||||||
maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
|
maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
|
||||||
total_packs = min(total_packs, maxpacks);
|
total_packs = min(total_packs, maxpacks);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
|
||||||
|
urb_packs >>= 1;
|
||||||
total_packs = MAX_URBS * urb_packs;
|
total_packs = MAX_URBS * urb_packs;
|
||||||
}
|
}
|
||||||
subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
|
subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
|
||||||
@ -1350,12 +1346,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
|
|||||||
subs->datapipe = usb_sndisocpipe(dev, ep);
|
subs->datapipe = usb_sndisocpipe(dev, ep);
|
||||||
else
|
else
|
||||||
subs->datapipe = usb_rcvisocpipe(dev, ep);
|
subs->datapipe = usb_rcvisocpipe(dev, ep);
|
||||||
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH &&
|
subs->datainterval = fmt->datainterval;
|
||||||
get_endpoint(alts, 0)->bInterval >= 1 &&
|
|
||||||
get_endpoint(alts, 0)->bInterval <= 4)
|
|
||||||
subs->datainterval = get_endpoint(alts, 0)->bInterval - 1;
|
|
||||||
else
|
|
||||||
subs->datainterval = 0;
|
|
||||||
subs->syncpipe = subs->syncinterval = 0;
|
subs->syncpipe = subs->syncinterval = 0;
|
||||||
subs->maxpacksize = fmt->maxpacksize;
|
subs->maxpacksize = fmt->maxpacksize;
|
||||||
subs->fill_max = 0;
|
subs->fill_max = 0;
|
||||||
@ -1568,11 +1559,15 @@ static struct snd_pcm_hardware snd_usb_hardware =
|
|||||||
#define hwc_debug(fmt, args...) /**/
|
#define hwc_debug(fmt, args...) /**/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audioformat *fp)
|
static int hw_check_valid_format(struct snd_usb_substream *subs,
|
||||||
|
struct snd_pcm_hw_params *params,
|
||||||
|
struct audioformat *fp)
|
||||||
{
|
{
|
||||||
struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
||||||
struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||||
struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
|
||||||
|
struct snd_interval *pt = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
|
||||||
|
unsigned int ptime;
|
||||||
|
|
||||||
/* check the format */
|
/* check the format */
|
||||||
if (!snd_mask_test(fmts, fp->format)) {
|
if (!snd_mask_test(fmts, fp->format)) {
|
||||||
@ -1593,6 +1588,14 @@ static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audiof
|
|||||||
hwc_debug(" > check: rate_max %d < min %d\n", fp->rate_max, it->min);
|
hwc_debug(" > check: rate_max %d < min %d\n", fp->rate_max, it->min);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* check whether the period time is >= the data packet interval */
|
||||||
|
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) {
|
||||||
|
ptime = 125 * (1 << fp->datainterval);
|
||||||
|
if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
|
||||||
|
hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1611,7 +1614,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
|
|||||||
list_for_each(p, &subs->fmt_list) {
|
list_for_each(p, &subs->fmt_list) {
|
||||||
struct audioformat *fp;
|
struct audioformat *fp;
|
||||||
fp = list_entry(p, struct audioformat, list);
|
fp = list_entry(p, struct audioformat, list);
|
||||||
if (!hw_check_valid_format(params, fp))
|
if (!hw_check_valid_format(subs, params, fp))
|
||||||
continue;
|
continue;
|
||||||
if (changed++) {
|
if (changed++) {
|
||||||
if (rmin > fp->rate_min)
|
if (rmin > fp->rate_min)
|
||||||
@ -1665,7 +1668,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
|
|||||||
list_for_each(p, &subs->fmt_list) {
|
list_for_each(p, &subs->fmt_list) {
|
||||||
struct audioformat *fp;
|
struct audioformat *fp;
|
||||||
fp = list_entry(p, struct audioformat, list);
|
fp = list_entry(p, struct audioformat, list);
|
||||||
if (!hw_check_valid_format(params, fp))
|
if (!hw_check_valid_format(subs, params, fp))
|
||||||
continue;
|
continue;
|
||||||
if (changed++) {
|
if (changed++) {
|
||||||
if (rmin > fp->channels)
|
if (rmin > fp->channels)
|
||||||
@ -1718,7 +1721,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
|
|||||||
list_for_each(p, &subs->fmt_list) {
|
list_for_each(p, &subs->fmt_list) {
|
||||||
struct audioformat *fp;
|
struct audioformat *fp;
|
||||||
fp = list_entry(p, struct audioformat, list);
|
fp = list_entry(p, struct audioformat, list);
|
||||||
if (!hw_check_valid_format(params, fp))
|
if (!hw_check_valid_format(subs, params, fp))
|
||||||
continue;
|
continue;
|
||||||
fbits |= (1ULL << fp->format);
|
fbits |= (1ULL << fp->format);
|
||||||
}
|
}
|
||||||
@ -1736,95 +1739,42 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
|
|||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_MASK 64
|
static int hw_rule_period_time(struct snd_pcm_hw_params *params,
|
||||||
|
struct snd_pcm_hw_rule *rule)
|
||||||
/*
|
|
||||||
* check whether the registered audio formats need special hw-constraints
|
|
||||||
*/
|
|
||||||
static int check_hw_params_convention(struct snd_usb_substream *subs)
|
|
||||||
{
|
{
|
||||||
int i;
|
struct snd_usb_substream *subs = rule->private;
|
||||||
u32 *channels;
|
struct audioformat *fp;
|
||||||
u32 *rates;
|
struct snd_interval *it;
|
||||||
u32 cmaster, rmaster;
|
unsigned char min_datainterval;
|
||||||
u32 rate_min = 0, rate_max = 0;
|
unsigned int pmin;
|
||||||
struct list_head *p;
|
int changed;
|
||||||
int err = 1;
|
|
||||||
|
|
||||||
channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
|
it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
|
||||||
rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
|
hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max);
|
||||||
if (!channels || !rates) {
|
min_datainterval = 0xff;
|
||||||
err = -ENOMEM;
|
list_for_each_entry(fp, &subs->fmt_list, list) {
|
||||||
goto __out;
|
if (!hw_check_valid_format(subs, params, fp))
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each(p, &subs->fmt_list) {
|
|
||||||
struct audioformat *f;
|
|
||||||
f = list_entry(p, struct audioformat, list);
|
|
||||||
/* unconventional channels? */
|
|
||||||
if (f->channels > 32)
|
|
||||||
goto __out;
|
|
||||||
/* continuous rate min/max matches? */
|
|
||||||
if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) {
|
|
||||||
if (rate_min && f->rate_min != rate_min)
|
|
||||||
goto __out;
|
|
||||||
if (rate_max && f->rate_max != rate_max)
|
|
||||||
goto __out;
|
|
||||||
rate_min = f->rate_min;
|
|
||||||
rate_max = f->rate_max;
|
|
||||||
}
|
|
||||||
/* combination of continuous rates and fixed rates? */
|
|
||||||
if (rates[f->format] & SNDRV_PCM_RATE_CONTINUOUS) {
|
|
||||||
if (f->rates != rates[f->format])
|
|
||||||
goto __out;
|
|
||||||
}
|
|
||||||
if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) {
|
|
||||||
if (rates[f->format] && rates[f->format] != f->rates)
|
|
||||||
goto __out;
|
|
||||||
}
|
|
||||||
channels[f->format] |= 1 << (f->channels - 1);
|
|
||||||
rates[f->format] |= f->rates;
|
|
||||||
/* needs knot? */
|
|
||||||
if (f->rates & SNDRV_PCM_RATE_KNOT)
|
|
||||||
goto __out;
|
|
||||||
}
|
|
||||||
/* check whether channels and rates match for all formats */
|
|
||||||
cmaster = rmaster = 0;
|
|
||||||
for (i = 0; i < MAX_MASK; i++) {
|
|
||||||
if (cmaster != channels[i] && cmaster && channels[i])
|
|
||||||
goto __out;
|
|
||||||
if (rmaster != rates[i] && rmaster && rates[i])
|
|
||||||
goto __out;
|
|
||||||
if (channels[i])
|
|
||||||
cmaster = channels[i];
|
|
||||||
if (rates[i])
|
|
||||||
rmaster = rates[i];
|
|
||||||
}
|
|
||||||
/* check whether channels match for all distinct rates */
|
|
||||||
memset(channels, 0, MAX_MASK * sizeof(u32));
|
|
||||||
list_for_each(p, &subs->fmt_list) {
|
|
||||||
struct audioformat *f;
|
|
||||||
f = list_entry(p, struct audioformat, list);
|
|
||||||
if (f->rates & SNDRV_PCM_RATE_CONTINUOUS)
|
|
||||||
continue;
|
continue;
|
||||||
for (i = 0; i < 32; i++) {
|
min_datainterval = min(min_datainterval, fp->datainterval);
|
||||||
if (f->rates & (1 << i))
|
|
||||||
channels[i] |= 1 << (f->channels - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cmaster = 0;
|
if (min_datainterval == 0xff) {
|
||||||
for (i = 0; i < 32; i++) {
|
hwc_debug(" --> get emtpy\n");
|
||||||
if (cmaster != channels[i] && cmaster && channels[i])
|
it->empty = 1;
|
||||||
goto __out;
|
return -EINVAL;
|
||||||
if (channels[i])
|
|
||||||
cmaster = channels[i];
|
|
||||||
}
|
}
|
||||||
err = 0;
|
pmin = 125 * (1 << min_datainterval);
|
||||||
|
changed = 0;
|
||||||
__out:
|
if (it->min < pmin) {
|
||||||
kfree(channels);
|
it->min = pmin;
|
||||||
kfree(rates);
|
it->openmin = 0;
|
||||||
return err;
|
changed = 1;
|
||||||
|
}
|
||||||
|
if (snd_interval_checkempty(it)) {
|
||||||
|
it->empty = 1;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
hwc_debug(" --> (%u,%u) (changed = %d)\n", it->min, it->max, changed);
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1872,6 +1822,8 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
|
|||||||
static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
|
static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
|
||||||
{
|
{
|
||||||
struct list_head *p;
|
struct list_head *p;
|
||||||
|
unsigned int pt, ptmin;
|
||||||
|
int param_period_time_if_needed;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
runtime->hw.formats = subs->formats;
|
runtime->hw.formats = subs->formats;
|
||||||
@ -1881,6 +1833,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
|
|||||||
runtime->hw.channels_min = 256;
|
runtime->hw.channels_min = 256;
|
||||||
runtime->hw.channels_max = 0;
|
runtime->hw.channels_max = 0;
|
||||||
runtime->hw.rates = 0;
|
runtime->hw.rates = 0;
|
||||||
|
ptmin = UINT_MAX;
|
||||||
/* check min/max rates and channels */
|
/* check min/max rates and channels */
|
||||||
list_for_each(p, &subs->fmt_list) {
|
list_for_each(p, &subs->fmt_list) {
|
||||||
struct audioformat *fp;
|
struct audioformat *fp;
|
||||||
@ -1899,42 +1852,54 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
|
|||||||
runtime->hw.period_bytes_min = runtime->hw.period_bytes_max =
|
runtime->hw.period_bytes_min = runtime->hw.period_bytes_max =
|
||||||
fp->frame_size;
|
fp->frame_size;
|
||||||
}
|
}
|
||||||
|
pt = 125 * (1 << fp->datainterval);
|
||||||
|
ptmin = min(ptmin, pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the period time minimum 1ms */
|
param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
|
||||||
/* FIXME: high-speed mode allows 125us minimum period, but many parts
|
if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH)
|
||||||
* in the current code assume the 1ms period.
|
/* full speed devices have fixed data packet interval */
|
||||||
*/
|
ptmin = 1000;
|
||||||
|
if (ptmin == 1000)
|
||||||
|
/* if period time doesn't go below 1 ms, no rules needed */
|
||||||
|
param_period_time_if_needed = -1;
|
||||||
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
|
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
|
||||||
1000,
|
ptmin, UINT_MAX);
|
||||||
/*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
|
|
||||||
|
|
||||||
err = check_hw_params_convention(subs);
|
if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
||||||
if (err < 0)
|
hw_rule_rate, subs,
|
||||||
|
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||||
|
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||||
|
param_period_time_if_needed,
|
||||||
|
-1)) < 0)
|
||||||
return err;
|
return err;
|
||||||
else if (err) {
|
if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||||
hwc_debug("setting extra hw constraints...\n");
|
hw_rule_channels, subs,
|
||||||
if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||||
hw_rule_rate, subs,
|
SNDRV_PCM_HW_PARAM_RATE,
|
||||||
SNDRV_PCM_HW_PARAM_FORMAT,
|
param_period_time_if_needed,
|
||||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
-1)) < 0)
|
||||||
-1)) < 0)
|
return err;
|
||||||
return err;
|
if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
|
||||||
if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
hw_rule_format, subs,
|
||||||
hw_rule_channels, subs,
|
SNDRV_PCM_HW_PARAM_RATE,
|
||||||
SNDRV_PCM_HW_PARAM_FORMAT,
|
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||||
SNDRV_PCM_HW_PARAM_RATE,
|
param_period_time_if_needed,
|
||||||
-1)) < 0)
|
-1)) < 0)
|
||||||
return err;
|
return err;
|
||||||
if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
|
if (param_period_time_if_needed >= 0) {
|
||||||
hw_rule_format, subs,
|
err = snd_pcm_hw_rule_add(runtime, 0,
|
||||||
SNDRV_PCM_HW_PARAM_RATE,
|
SNDRV_PCM_HW_PARAM_PERIOD_TIME,
|
||||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
hw_rule_period_time, subs,
|
||||||
-1)) < 0)
|
SNDRV_PCM_HW_PARAM_FORMAT,
|
||||||
return err;
|
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||||
if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
|
SNDRV_PCM_HW_PARAM_RATE,
|
||||||
|
-1);
|
||||||
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
|
||||||
|
return err;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2147,7 +2112,8 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
|
|||||||
fp = list_entry(p, struct audioformat, list);
|
fp = list_entry(p, struct audioformat, list);
|
||||||
snd_iprintf(buffer, " Interface %d\n", fp->iface);
|
snd_iprintf(buffer, " Interface %d\n", fp->iface);
|
||||||
snd_iprintf(buffer, " Altset %d\n", fp->altsetting);
|
snd_iprintf(buffer, " Altset %d\n", fp->altsetting);
|
||||||
snd_iprintf(buffer, " Format: %#x\n", fp->format);
|
snd_iprintf(buffer, " Format: %#x (%d bits)\n",
|
||||||
|
fp->format, snd_pcm_format_width(fp->format));
|
||||||
snd_iprintf(buffer, " Channels: %d\n", fp->channels);
|
snd_iprintf(buffer, " Channels: %d\n", fp->channels);
|
||||||
snd_iprintf(buffer, " Endpoint: %d %s (%s)\n",
|
snd_iprintf(buffer, " Endpoint: %d %s (%s)\n",
|
||||||
fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
|
fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
|
||||||
@ -2166,6 +2132,9 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
|
|||||||
}
|
}
|
||||||
snd_iprintf(buffer, "\n");
|
snd_iprintf(buffer, "\n");
|
||||||
}
|
}
|
||||||
|
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
|
||||||
|
snd_iprintf(buffer, " Data packet interval: %d us\n",
|
||||||
|
125 * (1 << fp->datainterval));
|
||||||
// snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
|
// snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
|
||||||
// snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes);
|
// snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes);
|
||||||
}
|
}
|
||||||
@ -2659,6 +2628,17 @@ static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned char parse_datainterval(struct snd_usb_audio *chip,
|
||||||
|
struct usb_host_interface *alts)
|
||||||
|
{
|
||||||
|
if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH &&
|
||||||
|
get_endpoint(alts, 0)->bInterval >= 1 &&
|
||||||
|
get_endpoint(alts, 0)->bInterval <= 4)
|
||||||
|
return get_endpoint(alts, 0)->bInterval - 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
|
static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
|
||||||
int iface, int altno);
|
int iface, int altno);
|
||||||
static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
||||||
@ -2764,6 +2744,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
|||||||
fp->altset_idx = i;
|
fp->altset_idx = i;
|
||||||
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
|
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
|
||||||
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
|
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
|
||||||
|
fp->datainterval = parse_datainterval(chip, alts);
|
||||||
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
||||||
if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
|
if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
|
||||||
fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
|
fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
|
||||||
@ -2955,6 +2936,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
alts = &iface->altsetting[fp->altset_idx];
|
alts = &iface->altsetting[fp->altset_idx];
|
||||||
|
fp->datainterval = parse_datainterval(chip, alts);
|
||||||
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
||||||
usb_set_interface(chip->dev, fp->iface, 0);
|
usb_set_interface(chip->dev, fp->iface, 0);
|
||||||
init_usb_pitch(chip->dev, fp->iface, alts, fp);
|
init_usb_pitch(chip->dev, fp->iface, alts, fp);
|
||||||
@ -3049,6 +3031,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
|
|||||||
fp->iface = altsd->bInterfaceNumber;
|
fp->iface = altsd->bInterfaceNumber;
|
||||||
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
|
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
|
||||||
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
|
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
|
||||||
|
fp->datainterval = 0;
|
||||||
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
||||||
|
|
||||||
switch (fp->maxpacksize) {
|
switch (fp->maxpacksize) {
|
||||||
@ -3116,6 +3099,7 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip,
|
|||||||
fp->iface = altsd->bInterfaceNumber;
|
fp->iface = altsd->bInterfaceNumber;
|
||||||
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
|
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
|
||||||
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
|
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
|
||||||
|
fp->datainterval = parse_datainterval(chip, alts);
|
||||||
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
||||||
fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);
|
fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);
|
||||||
|
|
||||||
@ -3168,6 +3152,7 @@ static int create_ua101_quirk(struct snd_usb_audio *chip,
|
|||||||
fp->iface = altsd->bInterfaceNumber;
|
fp->iface = altsd->bInterfaceNumber;
|
||||||
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
|
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
|
||||||
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
|
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
|
||||||
|
fp->datainterval = parse_datainterval(chip, alts);
|
||||||
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
|
||||||
fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]);
|
fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user