cregit-Linux how code gets into the kernel

Release 4.11 sound/usb/line6/pcm.c

Directory: sound/usb/line6
/*
 * Line 6 Linux USB driver
 *
 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License as
 *      published by the Free Software Foundation, version 2.
 *
 */

#include <linux/slab.h>
#include <linux/export.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>

#include "capture.h"
#include "driver.h"
#include "playback.h"

/* impulse response volume controls */

static int snd_line6_impulse_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 255; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai4078.43%150.00%
Markus Grabner1121.57%150.00%
Total51100.00%2100.00%


static int snd_line6_impulse_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = line6pcm->impulse_volume; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai2965.91%150.00%
Markus Grabner1534.09%150.00%
Total44100.00%2100.00%


static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); int value = ucontrol->value.integer.value[0]; int err; if (line6pcm->impulse_volume == value) return 0; line6pcm->impulse_volume = value; if (value > 0) { err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE, true); if (err < 0) { line6pcm->impulse_volume = 0; return err; } } else { line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE); } return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai5449.54%342.86%
Markus Grabner4743.12%228.57%
Johannes Thumshirn65.50%114.29%
Andrej Krutak21.83%114.29%
Total109100.00%7100.00%

/* impulse response period controls */
static int snd_line6_impulse_period_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 2000; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai4486.27%150.00%
Markus Grabner713.73%150.00%
Total51100.00%2100.00%


static int snd_line6_impulse_period_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); ucontrol->value.integer.value[0] = line6pcm->impulse_period; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai3477.27%150.00%
Markus Grabner1022.73%150.00%
Total44100.00%2100.00%


static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); int value = ucontrol->value.integer.value[0]; if (line6pcm->impulse_period == value) return 0; line6pcm->impulse_period = value; return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai3558.33%133.33%
Markus Grabner1626.67%133.33%
Laurent Navet915.00%133.33%
Total60100.00%3100.00%

/* Unlink all currently active URBs. */
static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm, struct line6_pcm_stream *pcms) { int i; for (i = 0; i < line6pcm->line6->iso_buffers; i++) { if (test_bit(i, &pcms->active_urbs)) { if (!test_and_set_bit(i, &pcms->unlink_urbs)) usb_unlink_urb(pcms->urbs[i]); } } }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai7093.33%150.00%
Andrej Krutak56.67%150.00%
Total75100.00%2100.00%

/* Wait until unlinking of all currently active URBs has been finished. */
static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm, struct line6_pcm_stream *pcms) { int timeout = HZ; int i; int alive; do { alive = 0; for (i = 0; i < line6pcm->line6->iso_buffers; i++) { if (test_bit(i, &pcms->active_urbs)) alive++; } if (!alive) break; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } while (--timeout > 0); if (alive) dev_err(line6pcm->line6->ifcdev, "timeout: still %d active urbs..\n", alive); }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai10495.41%266.67%
Andrej Krutak54.59%133.33%
Total109100.00%3100.00%


static inline struct line6_pcm_stream * get_stream(struct snd_line6_pcm *line6pcm, int direction) { return (direction == SNDRV_PCM_STREAM_PLAYBACK) ? &line6pcm->out : &line6pcm->in; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai34100.00%1100.00%
Total34100.00%1100.00%

/* allocate a buffer if not opened yet; * call this in line6pcm.state_mutex */
static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm, struct line6_pcm_stream *pstr, int direction, int type) { const int pkt_size = (direction == SNDRV_PCM_STREAM_PLAYBACK) ? line6pcm->max_packet_size_out : line6pcm->max_packet_size_in; /* Invoked multiple times in a row so allocate once only */ if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) { pstr->buffer = kmalloc(line6pcm->line6->iso_buffers * LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL); if (!pstr->buffer) return -ENOMEM; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai6771.28%250.00%
Andrej Krutak2728.72%250.00%
Total94100.00%4100.00%

/* free a buffer if all streams are closed; * call this in line6pcm.state_mutex */
static void line6_buffer_release(struct snd_line6_pcm *line6pcm, struct line6_pcm_stream *pstr, int type) { clear_bit(type, &pstr->opened); if (!pstr->opened) { line6_wait_clear_audio_urbs(line6pcm, pstr); kfree(pstr->buffer); pstr->buffer = NULL; } }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai5798.28%266.67%
Markus Grabner11.72%133.33%
Total58100.00%3100.00%

/* start a PCM stream */
static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, int type) { unsigned long flags; struct line6_pcm_stream *pstr = get_stream(line6pcm, direction); int ret = 0; spin_lock_irqsave(&pstr->lock, flags); if (!test_and_set_bit(type, &pstr->running) && !(pstr->active_urbs || pstr->unlink_urbs)) { pstr->count = 0; /* Submit all currently available URBs */ if (direction == SNDRV_PCM_STREAM_PLAYBACK) ret = line6_submit_audio_out_all_urbs(line6pcm); else ret = line6_submit_audio_in_all_urbs(line6pcm); } if (ret < 0) clear_bit(type, &pstr->running); spin_unlock_irqrestore(&pstr->lock, flags); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai7960.31%555.56%
Markus Grabner4534.35%333.33%
Arnd Bergmann75.34%111.11%
Total131100.00%9100.00%

/* stop a PCM stream; this doesn't sync with the unlinked URBs */
static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction, int type) { unsigned long flags; struct line6_pcm_stream *pstr = get_stream(line6pcm, direction); spin_lock_irqsave(&pstr->lock, flags); clear_bit(type, &pstr->running); if (!pstr->running) { spin_unlock_irqrestore(&pstr->lock, flags); line6_unlink_audio_urbs(line6pcm, pstr); spin_lock_irqsave(&pstr->lock, flags); if (direction == SNDRV_PCM_STREAM_CAPTURE) { line6pcm->prev_fbuf = NULL; line6pcm->prev_fsize = 0; } } spin_unlock_irqrestore(&pstr->lock, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai9075.63%133.33%
Andrej Krutak2016.81%133.33%
Markus Grabner97.56%133.33%
Total119100.00%3100.00%

/* common PCM trigger callback */
int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct snd_pcm_substream *s; int err; clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags); snd_pcm_group_for_each_entry(s, substream) { if (s->pcm->card != substream->pcm->card) continue; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: if (s->stream == SNDRV_PCM_STREAM_CAPTURE && (line6pcm->line6->properties->capabilities & LINE6_CAP_IN_NEEDS_OUT)) { err = line6_stream_start(line6pcm, SNDRV_PCM_STREAM_PLAYBACK, LINE6_STREAM_CAPTURE_HELPER); if (err < 0) return err; } err = line6_stream_start(line6pcm, s->stream, LINE6_STREAM_PCM); if (err < 0) return err; break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: if (s->stream == SNDRV_PCM_STREAM_CAPTURE && (line6pcm->line6->properties->capabilities & LINE6_CAP_IN_NEEDS_OUT)) { line6_stream_stop(line6pcm, SNDRV_PCM_STREAM_PLAYBACK, LINE6_STREAM_CAPTURE_HELPER); } line6_stream_stop(line6pcm, s->stream, LINE6_STREAM_PCM); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) return -EINVAL; set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) return -EINVAL; clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags); break; default: return -EINVAL; } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai15963.60%133.33%
Andrej Krutak7329.20%133.33%
Markus Grabner187.20%133.33%
Total250100.00%3100.00%

/* common PCM pointer callback */
snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream) { struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); return pstr->pos_done; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai39100.00%1100.00%
Total39100.00%1100.00%

/* Acquire and optionally start duplex streams: * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR */
int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start) { struct line6_pcm_stream *pstr; int ret = 0, dir; /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */ mutex_lock(&line6pcm->state_mutex); for (dir = 0; dir < 2; dir++) { pstr = get_stream(line6pcm, dir); ret = line6_buffer_acquire(line6pcm, pstr, dir, type); if (ret < 0) goto error; if (!pstr->running) line6_wait_clear_audio_urbs(line6pcm, pstr); } if (start) { for (dir = 0; dir < 2; dir++) { ret = line6_stream_start(line6pcm, dir, type); if (ret < 0) goto error; } } error: mutex_unlock(&line6pcm->state_mutex); if (ret < 0) line6_pcm_release(line6pcm, type); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai12274.39%116.67%
Markus Grabner3018.29%350.00%
Andrej Krutak127.32%233.33%
Total164100.00%6100.00%

EXPORT_SYMBOL_GPL(line6_pcm_acquire); /* Stop and release duplex streams */
void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type) { struct line6_pcm_stream *pstr; int dir; mutex_lock(&line6pcm->state_mutex); for (dir = 0; dir < 2; dir++) line6_stream_stop(line6pcm, dir, type); for (dir = 0; dir < 2; dir++) { pstr = get_stream(line6pcm, dir); line6_buffer_release(line6pcm, pstr, type); } mutex_unlock(&line6pcm->state_mutex); }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai6671.74%342.86%
Markus Grabner1920.65%342.86%
Arnd Bergmann77.61%114.29%
Total92100.00%7100.00%

EXPORT_SYMBOL_GPL(line6_pcm_release); /* common PCM hw_params callback */
int snd_line6_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { int ret; struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); mutex_lock(&line6pcm->state_mutex); ret = line6_buffer_acquire(line6pcm, pstr, substream->stream, LINE6_STREAM_PCM); if (ret < 0) goto error; ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); if (ret < 0) { line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM); goto error; } pstr->period = params_period_bytes(hw_params); error: mutex_unlock(&line6pcm->state_mutex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai9473.44%342.86%
Markus Grabner3023.44%342.86%
Andrej Krutak43.12%114.29%
Total128100.00%7100.00%

/* common PCM hw_free callback */
int snd_line6_hw_free(struct snd_pcm_substream *substream) { struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); mutex_lock(&line6pcm->state_mutex); line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM); mutex_unlock(&line6pcm->state_mutex); return snd_pcm_lib_free_pages(substream); }

Contributors

PersonTokensPropCommitsCommitProp
Markus Grabner4163.08%240.00%
Takashi Iwai2436.92%360.00%
Total65100.00%5100.00%

/* control info callback */
static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 256; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Markus Grabner51100.00%2100.00%
Total51100.00%2100.00%

/* control get callback */
static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int i; struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); for (i = 0; i < 2; i++) ucontrol->value.integer.value[i] = line6pcm->volume_playback[i]; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Markus Grabner5892.06%266.67%
Takashi Iwai57.94%133.33%
Total63100.00%3100.00%

/* control put callback */
static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int i, changed = 0; struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); for (i = 0; i < 2; i++) if (line6pcm->volume_playback[i] != ucontrol->value.integer.value[i]) { line6pcm->volume_playback[i] = ucontrol->value.integer.value[i]; changed = 1; } return changed; }

Contributors

PersonTokensPropCommitsCommitProp
Markus Grabner8894.62%266.67%
Takashi Iwai55.38%133.33%
Total93100.00%3100.00%

/* control definition */ static struct snd_kcontrol_new line6_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", .info = snd_line6_control_playback_info, .get = snd_line6_control_playback_get, .put = snd_line6_control_playback_put }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Impulse Response Volume", .info = snd_line6_impulse_volume_info, .get = snd_line6_impulse_volume_get, .put = snd_line6_impulse_volume_put }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Impulse Response Period", .info = snd_line6_impulse_period_info, .get = snd_line6_impulse_period_get, .put = snd_line6_impulse_period_put }, }; /* Cleanup the PCM device. */
static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers) { int i; /* Most likely impossible in current code... */ if (pcms->urbs == NULL) return; for (i = 0; i < iso_buffers; i++) { if (pcms->urbs[i]) { usb_kill_urb(pcms->urbs[i]); usb_free_urb(pcms->urbs[i]); } } kfree(pcms->urbs); pcms->urbs = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Markus Grabner4451.16%120.00%
Andrej Krutak2731.40%120.00%
Takashi Iwai1517.44%360.00%
Total86100.00%5100.00%


static void line6_cleanup_pcm(struct snd_pcm *pcm) { struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers); cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers); kfree(line6pcm); }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai3055.56%360.00%
Andrej Krutak1222.22%120.00%
Markus Grabner1222.22%120.00%
Total54100.00%5100.00%

/* create a PCM device */
static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret) { struct snd_pcm *pcm; int err; err = snd_pcm_new(line6->card, (char *)line6->properties->name, 0, 1, 1, pcm_ret); if (err < 0) return err; pcm = *pcm_ret; strcpy(pcm->name, line6->properties->name); /* set operators */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_line6_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops); /* pre-allocation of buffers */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), 64 * 1024, 128 * 1024); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Markus Grabner10987.90%133.33%
Takashi Iwai118.87%133.33%
Greg Kroah-Hartman43.23%133.33%
Total124100.00%3100.00%

/* Sync with PCM stream stops. */
void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm) { line6_unlink_audio_urbs(line6pcm, &line6pcm->out); line6_unlink_audio_urbs(line6pcm, &line6pcm->in); line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out); line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in); }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai3264.00%150.00%
Markus Grabner1836.00%150.00%
Total50100.00%2100.00%

/* Create and register the PCM device and mixer entries. Create URBs for playback and capture. */
int line6_init_pcm(struct usb_line6 *line6, struct line6_pcm_properties *properties) { int i, err; unsigned ep_read = line6->properties->ep_audio_r; unsigned ep_write = line6->properties->ep_audio_w; struct snd_pcm *pcm; struct snd_line6_pcm *line6pcm; if (!(line6->properties->capabilities & LINE6_CAP_PCM)) return 0; /* skip PCM initialization and report success */ err = snd_line6_new_pcm(line6, &pcm); if (err < 0) return err; line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL); if (!line6pcm) return -ENOMEM; mutex_init(&line6pcm->state_mutex); line6pcm->pcm = pcm; line6pcm->properties = properties; line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255; line6pcm->volume_monitor = 255; line6pcm->line6 = line6; line6pcm->max_packet_size_in = usb_maxpacket(line6->usbdev, usb_rcvisocpipe(line6->usbdev, ep_read), 0); line6pcm->max_packet_size_out = usb_maxpacket(line6->usbdev, usb_sndisocpipe(line6->usbdev, ep_write), 1); spin_lock_init(&line6pcm->out.lock); spin_lock_init(&line6pcm->in.lock); line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD; line6->line6pcm = line6pcm; pcm->private_data = line6pcm; pcm->private_free = line6_cleanup_pcm; err = line6_create_audio_out_urbs(line6pcm); if (err < 0) return err; err = line6_create_audio_in_urbs(line6pcm); if (err < 0) return err; /* mixer: */ for (i = 0; i < ARRAY_SIZE(line6_controls); i++) { err = snd_ctl_add(line6->card, snd_ctl_new1(&line6_controls[i], line6pcm)); if (err < 0) return err; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Markus Grabner17453.54%216.67%
Takashi Iwai9930.46%433.33%
Stefan Hajnoczi185.54%18.33%
Chris Rorvick144.31%216.67%
Greg Kroah-Hartman123.69%18.33%
Andrej Krutak61.85%18.33%
L. Alberto Giménez20.62%18.33%
Total325100.00%12100.00%

EXPORT_SYMBOL_GPL(line6_init_pcm); /* prepare pcm callback */
int snd_line6_prepare(struct snd_pcm_substream *substream) { struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); mutex_lock(&line6pcm->state_mutex); if (!pstr->running) line6_wait_clear_audio_urbs(line6pcm, pstr); if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) { line6pcm->out.count = 0; line6pcm->out.pos = 0; line6pcm->out.pos_done = 0; line6pcm->out.bytes = 0; line6pcm->in.count = 0; line6pcm->in.pos_done = 0; line6pcm->in.bytes = 0; } mutex_unlock(&line6pcm->state_mutex); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Markus Grabner7655.07%342.86%
Takashi Iwai5842.03%342.86%
Stefan Hajnoczi42.90%114.29%
Total138100.00%7100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Takashi Iwai158155.36%1747.22%
Markus Grabner99234.73%411.11%
Andrej Krutak1966.86%411.11%
Stefan Hajnoczi220.77%25.56%
Greg Kroah-Hartman160.56%12.78%
Chris Rorvick150.53%38.33%
Arnd Bergmann140.49%12.78%
Laurent Navet90.32%12.78%
Johannes Thumshirn60.21%12.78%
Tejun Heo30.11%12.78%
L. Alberto Giménez20.07%12.78%
Total2856100.00%36100.00%
Directory: sound/usb/line6
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.