summarylogtreecommitdiffstats
path: root/parameters.patch
blob: e516e67cd0bcdac2155e0e8a1c0dfb5052e9c99c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
diff --git a/sound/usb/card.c b/sound/usb/card.c
index a1ed798a1c6b..6d7f1a8a7fe1 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -81,6 +81,11 @@ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card *
 /* Vendor/product IDs for this card */
 static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
+static int max_packs = 6;	/* per URB */
+static int max_packs_hs = 6 * 8;	/* in high speed mode */
+static int max_urbs = 12;
+static int sync_urbs = 4;	/* always four urbs for sync */
+static int max_queue = 18;	/* try not to exceed this queue length, in ms */
 static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
 static bool ignore_ctl_error;
 static bool autoclock = true;
@@ -98,6 +103,16 @@ module_param_array(vid, int, NULL, 0444);
 MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
 module_param_array(pid, int, NULL, 0444);
 MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
+module_param(max_packs, int, 0644);
+MODULE_PARM_DESC(max_packs, "Max. number of packets per URB in low speed mode");
+module_param(max_packs_hs, int, 0644);
+MODULE_PARM_DESC(max_packs_hs, "Max. number of packets per URB in high speed mode");
+module_param(max_urbs, int, 0644);
+MODULE_PARM_DESC(max_urbs, "Max. number of URBs");
+module_param(sync_urbs, int, 0644);
+MODULE_PARM_DESC(sync_urbs, "Number of URBs for sync");
+module_param(max_queue, int, 0644);
+MODULE_PARM_DESC(max_queue, "Try not to exceed this queue length, in ms");
 module_param_array(device_setup, int, NULL, 0444);
 MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
 module_param(ignore_ctl_error, bool, 0444);
@@ -486,6 +501,16 @@ static int snd_usb_audio_create(struct usb_interface *intf,
 	chip->dev = dev;
 	chip->card = card;
 	chip->setup = device_setup[idx];
+	chip->max_packs = min(max(1, max_packs), MAX_PACKS_LIMIT);
+	dev_info(&dev->dev, "snd-usb-audio: max_packs: %d\n", chip->max_packs);
+	chip->max_packs_hs = min(max(1, max_packs_hs), MAX_PACKS_LIMIT);
+	dev_info(&dev->dev, "snd-usb-audio: max_packs_hs: %d\n", chip->max_packs_hs);
+	chip->max_urbs = min(max(1, max_urbs), MAX_URBS_LIMIT);
+	dev_info(&dev->dev, "snd-usb-audio: max_urbs: %d\n", chip->max_urbs);
+	chip->sync_urbs = min(max(1, sync_urbs), MAX_URBS_LIMIT);
+	dev_info(&dev->dev, "snd-usb-audio: sync_urbs: %d\n", chip->sync_urbs);
+	chip->max_queue = max(1, max_queue);
+	dev_info(&dev->dev, "snd-usb-audio: max_queue: %d\n", chip->max_queue);
 	chip->autoclock = autoclock;
 	atomic_set(&chip->active, 1); /* avoid autopm during probing */
 	atomic_set(&chip->usage_count, 0);
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 9b41b7dda84f..40e106042bb9 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -3,11 +3,8 @@
 #define __USBAUDIO_CARD_H
 
 #define MAX_NR_RATES	1024
-#define MAX_PACKS	6		/* per URB */
-#define MAX_PACKS_HS	(MAX_PACKS * 8)	/* in high speed mode */
-#define MAX_URBS	12
-#define SYNC_URBS	4	/* always four urbs for sync */
-#define MAX_QUEUE	18	/* try not to exceed this queue length, in ms */
+#define MAX_PACKS_LIMIT	64
+#define MAX_URBS_LIMIT	32
 
 struct audioformat {
 	struct list_head list;
@@ -45,7 +42,7 @@ struct snd_urb_ctx {
 	struct snd_usb_endpoint *ep;
 	int index;	/* index for urb array */
 	int packets;	/* number of packets per urb */
-	int packet_size[MAX_PACKS_HS]; /* size of packets for next submission */
+	int packet_size[MAX_PACKS_LIMIT];	/* size of packets for next submission */
 	struct list_head ready_list;
 };
 
@@ -66,12 +63,12 @@ struct snd_usb_endpoint {
 	struct snd_usb_endpoint *sync_master;
 	struct snd_usb_endpoint *sync_slave;
 
-	struct snd_urb_ctx urb[MAX_URBS];
+	struct snd_urb_ctx urb[MAX_URBS_LIMIT];
 
 	struct snd_usb_packet_info {
-		uint32_t packet_size[MAX_PACKS_HS];
+		uint32_t packet_size[MAX_PACKS_LIMIT];
 		int packets;
-	} next_packet[MAX_URBS];
+	} next_packet[MAX_URBS_LIMIT];
 	int next_packet_read_pos, next_packet_write_pos;
 	struct list_head ready_playback_urbs;
 
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index c90607ebe155..8980cc16284c 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -332,7 +332,7 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
 		if (ep->next_packet_read_pos != ep->next_packet_write_pos) {
 			packet = ep->next_packet + ep->next_packet_read_pos;
 			ep->next_packet_read_pos++;
-			ep->next_packet_read_pos %= MAX_URBS;
+			ep->next_packet_read_pos %= ep->chip->max_urbs;
 
 			/* take URB out of FIFO */
 			if (!list_empty(&ep->ready_playback_urbs))
@@ -601,7 +601,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
 		release_urb_ctx(&ep->urb[i]);
 
 	if (ep->syncbuf)
-		usb_free_coherent(ep->chip->dev, SYNC_URBS * 4,
+		usb_free_coherent(ep->chip->dev, ep->chip->sync_urbs * 4,
 				  ep->syncbuf, ep->sync_dma);
 
 	ep->syncbuf = NULL;
@@ -694,10 +694,10 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 
 	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) {
 		packs_per_ms = 8 >> ep->datainterval;
-		max_packs_per_urb = MAX_PACKS_HS;
+		max_packs_per_urb = ep->chip->max_packs_hs;
 	} else {
 		packs_per_ms = 1;
-		max_packs_per_urb = MAX_PACKS;
+		max_packs_per_urb = ep->chip->max_packs;
 	}
 	if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
 		max_packs_per_urb = min(max_packs_per_urb,
@@ -733,13 +733,13 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 		urb_packs = min(max_packs_per_urb, urb_packs);
 		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
 			urb_packs >>= 1;
-		ep->nurbs = MAX_URBS;
+		ep->nurbs = ep->chip->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.
+	 * ALSA buffer, subject to the max_urbs and max_queue limits.
 	 */
 	} else {
 		/* determine how small a packet can be */
@@ -764,8 +764,8 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 					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);
+		max_urbs = min((unsigned int) ep->chip->max_urbs,
+				ep->chip->max_queue * packs_per_ms / urb_packs);
 		ep->nurbs = min(max_urbs, urbs_per_period * periods_per_buffer);
 	}
 
@@ -810,12 +810,12 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
 {
 	int i;
 
-	ep->syncbuf = usb_alloc_coherent(ep->chip->dev, SYNC_URBS * 4,
+	ep->syncbuf = usb_alloc_coherent(ep->chip->dev, ep->chip->sync_urbs * 4,
 					 GFP_KERNEL, &ep->sync_dma);
 	if (!ep->syncbuf)
 		return -ENOMEM;
 
-	for (i = 0; i < SYNC_URBS; i++) {
+	for (i = 0; i < ep->chip->sync_urbs; i++) {
 		struct snd_urb_ctx *u = &ep->urb[i];
 		u->index = i;
 		u->ep = ep;
@@ -834,7 +834,7 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
 		u->urb->complete = snd_complete_urb;
 	}
 
-	ep->nurbs = SYNC_URBS;
+	ep->nurbs = ep->chip->sync_urbs;
 
 	return 0;
 
@@ -1146,7 +1146,7 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 		}
 
 		ep->next_packet_write_pos++;
-		ep->next_packet_write_pos %= MAX_URBS;
+		ep->next_packet_write_pos %= ep->chip->max_urbs;
 		spin_unlock_irqrestore(&ep->lock, flags);
 		queue_pending_output_urbs(ep);
 
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index b9faeca645fd..f7a25935ca03 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -60,6 +60,11 @@ struct snd_usb_audio {
 	struct list_head mixer_list;	/* list of mixer interfaces */
 
 	int setup;			/* from the 'device_setup' module param */
+	int max_packs;			/* from the 'max_packs' module param */
+	int max_packs_hs;		/* from the 'max_packs_hs' module param */
+	int max_urbs;			/* from the 'max_urbs' module param */
+	int sync_urbs;			/* from the 'sync_urbs' module param */
+	int max_queue;			/* from the 'max_queue' module param */
 	bool autoclock;			/* from the 'autoclock' module param */
 	bool keep_iface;		/* keep interface/altset after closing
 					 * or parameter change