aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/6fire/pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/6fire/pcm.c')
-rw-r--r--sound/usb/6fire/pcm.c97
1 files changed, 38 insertions, 59 deletions
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
index ba62c7468ba8..b137b25865cc 100644
--- a/sound/usb/6fire/pcm.c
+++ b/sound/usb/6fire/pcm.c
@@ -17,26 +17,23 @@
17#include "pcm.h" 17#include "pcm.h"
18#include "chip.h" 18#include "chip.h"
19#include "comm.h" 19#include "comm.h"
20#include "control.h"
20 21
21enum { 22enum {
22 OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4 23 OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4
23}; 24};
24 25
25/* keep next two synced with 26/* keep next two synced with
26 * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE */ 27 * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE
28 * and CONTROL_RATE_XXX in control.h */
27static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 }; 29static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 };
28static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 }; 30static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 };
29static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; 31static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 };
30static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
31static const int rates_alsaid[] = { 32static const int rates_alsaid[] = {
32 SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000, 33 SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000,
33 SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000, 34 SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000,
34 SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 }; 35 SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 };
35 36
36/* values to write to soundcard register for all samplerates */
37static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
38static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
39
40enum { /* settings for pcm */ 37enum { /* settings for pcm */
41 OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024 38 OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024
42}; 39};
@@ -48,15 +45,6 @@ enum { /* pcm streaming states */
48 STREAM_STOPPING 45 STREAM_STOPPING
49}; 46};
50 47
51enum { /* pcm sample rates (also index into RATES_XXX[]) */
52 RATE_44KHZ,
53 RATE_48KHZ,
54 RATE_88KHZ,
55 RATE_96KHZ,
56 RATE_176KHZ,
57 RATE_192KHZ
58};
59
60static const struct snd_pcm_hardware pcm_hw = { 48static const struct snd_pcm_hardware pcm_hw = {
61 .info = SNDRV_PCM_INFO_MMAP | 49 .info = SNDRV_PCM_INFO_MMAP |
62 SNDRV_PCM_INFO_INTERLEAVED | 50 SNDRV_PCM_INFO_INTERLEAVED |
@@ -64,7 +52,7 @@ static const struct snd_pcm_hardware pcm_hw = {
64 SNDRV_PCM_INFO_MMAP_VALID | 52 SNDRV_PCM_INFO_MMAP_VALID |
65 SNDRV_PCM_INFO_BATCH, 53 SNDRV_PCM_INFO_BATCH,
66 54
67 .formats = SNDRV_PCM_FMTBIT_S24_LE, 55 .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
68 56
69 .rates = SNDRV_PCM_RATE_44100 | 57 .rates = SNDRV_PCM_RATE_44100 |
70 SNDRV_PCM_RATE_48000 | 58 SNDRV_PCM_RATE_48000 |
@@ -87,57 +75,34 @@ static const struct snd_pcm_hardware pcm_hw = {
87static int usb6fire_pcm_set_rate(struct pcm_runtime *rt) 75static int usb6fire_pcm_set_rate(struct pcm_runtime *rt)
88{ 76{
89 int ret; 77 int ret;
90 struct usb_device *device = rt->chip->dev; 78 struct control_runtime *ctrl_rt = rt->chip->control;
91 struct comm_runtime *comm_rt = rt->chip->comm;
92 79
93 if (rt->rate >= ARRAY_SIZE(rates)) 80 ctrl_rt->usb_streaming = false;
94 return -EINVAL; 81 ret = ctrl_rt->update_streaming(ctrl_rt);
95 /* disable streaming */
96 ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x00);
97 if (ret < 0) { 82 if (ret < 0) {
98 snd_printk(KERN_ERR PREFIX "error stopping streaming while " 83 snd_printk(KERN_ERR PREFIX "error stopping streaming while "
99 "setting samplerate %d.\n", rates[rt->rate]); 84 "setting samplerate %d.\n", rates[rt->rate]);
100 return ret; 85 return ret;
101 } 86 }
102 87
103 ret = usb_set_interface(device, 1, rates_altsetting[rt->rate]); 88 ret = ctrl_rt->set_rate(ctrl_rt, rt->rate);
104 if (ret < 0) {
105 snd_printk(KERN_ERR PREFIX "error setting interface "
106 "altsetting %d for samplerate %d.\n",
107 rates_altsetting[rt->rate], rates[rt->rate]);
108 return ret;
109 }
110
111 /* set soundcard clock */
112 ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rt->rate],
113 rates_6fire_vh[rt->rate]);
114 if (ret < 0) { 89 if (ret < 0) {
115 snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n", 90 snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n",
116 rates[rt->rate]); 91 rates[rt->rate]);
117 return ret; 92 return ret;
118 } 93 }
119 94
120 /* enable analog inputs and outputs 95 ret = ctrl_rt->set_channels(ctrl_rt, OUT_N_CHANNELS, IN_N_CHANNELS,
121 * (one bit per stereo-channel) */ 96 false, false);
122 ret = comm_rt->write16(comm_rt, 0x02, 0x02,
123 (1 << (OUT_N_CHANNELS / 2)) - 1,
124 (1 << (IN_N_CHANNELS / 2)) - 1);
125 if (ret < 0) { 97 if (ret < 0) {
126 snd_printk(KERN_ERR PREFIX "error initializing analog channels " 98 snd_printk(KERN_ERR PREFIX "error initializing channels "
127 "while setting samplerate %d.\n", 99 "while setting samplerate %d.\n",
128 rates[rt->rate]); 100 rates[rt->rate]);
129 return ret; 101 return ret;
130 } 102 }
131 /* disable digital inputs and outputs */
132 ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00);
133 if (ret < 0) {
134 snd_printk(KERN_ERR PREFIX "error initializing digital "
135 "channels while setting samplerate %d.\n",
136 rates[rt->rate]);
137 return ret;
138 }
139 103
140 ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x01); 104 ctrl_rt->usb_streaming = true;
105 ret = ctrl_rt->update_streaming(ctrl_rt);
141 if (ret < 0) { 106 if (ret < 0) {
142 snd_printk(KERN_ERR PREFIX "error starting streaming while " 107 snd_printk(KERN_ERR PREFIX "error starting streaming while "
143 "setting samplerate %d.\n", rates[rt->rate]); 108 "setting samplerate %d.\n", rates[rt->rate]);
@@ -168,12 +133,15 @@ static struct pcm_substream *usb6fire_pcm_get_substream(
168static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt) 133static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
169{ 134{
170 int i; 135 int i;
136 struct control_runtime *ctrl_rt = rt->chip->control;
171 137
172 if (rt->stream_state != STREAM_DISABLED) { 138 if (rt->stream_state != STREAM_DISABLED) {
173 for (i = 0; i < PCM_N_URBS; i++) { 139 for (i = 0; i < PCM_N_URBS; i++) {
174 usb_kill_urb(&rt->in_urbs[i].instance); 140 usb_kill_urb(&rt->in_urbs[i].instance);
175 usb_kill_urb(&rt->out_urbs[i].instance); 141 usb_kill_urb(&rt->out_urbs[i].instance);
176 } 142 }
143 ctrl_rt->usb_streaming = false;
144 ctrl_rt->update_streaming(ctrl_rt);
177 rt->stream_state = STREAM_DISABLED; 145 rt->stream_state = STREAM_DISABLED;
178 } 146 }
179} 147}
@@ -228,7 +196,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
228 unsigned int total_length = 0; 196 unsigned int total_length = 0;
229 struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); 197 struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
230 struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; 198 struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
231 u32 *src = (u32 *) urb->buffer; 199 u32 *src = NULL;
232 u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off 200 u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off
233 * (alsa_rt->frame_bits >> 3)); 201 * (alsa_rt->frame_bits >> 3));
234 u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size 202 u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
@@ -244,7 +212,12 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
244 else 212 else
245 frame_count = 0; 213 frame_count = 0;
246 214
247 src = (u32 *) (urb->buffer + total_length); 215 if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
216 src = (u32 *) (urb->buffer + total_length);
217 else if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE)
218 src = (u32 *) (urb->buffer - 1 + total_length);
219 else
220 return;
248 src++; /* skip leading 4 bytes of every packet */ 221 src++; /* skip leading 4 bytes of every packet */
249 total_length += urb->packets[i].length; 222 total_length += urb->packets[i].length;
250 for (frame = 0; frame < frame_count; frame++) { 223 for (frame = 0; frame < frame_count; frame++) {
@@ -274,9 +247,18 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub,
274 * (alsa_rt->frame_bits >> 3)); 247 * (alsa_rt->frame_bits >> 3));
275 u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size 248 u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
276 * (alsa_rt->frame_bits >> 3)); 249 * (alsa_rt->frame_bits >> 3));
277 u32 *dest = (u32 *) urb->buffer; 250 u32 *dest;
278 int bytes_per_frame = alsa_rt->channels << 2; 251 int bytes_per_frame = alsa_rt->channels << 2;
279 252
253 if (alsa_rt->format == SNDRV_PCM_FORMAT_S32_LE)
254 dest = (u32 *) (urb->buffer - 1);
255 else if (alsa_rt->format == SNDRV_PCM_FORMAT_S24_LE)
256 dest = (u32 *) (urb->buffer);
257 else {
258 snd_printk(KERN_ERR PREFIX "Unknown sample format.");
259 return;
260 }
261
280 for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { 262 for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
281 /* at least 4 header bytes for valid packet. 263 /* at least 4 header bytes for valid packet.
282 * after that: 32 bits per sample for analog channels */ 264 * after that: 32 bits per sample for analog channels */
@@ -456,7 +438,7 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
456 /* all substreams closed? if so, stop streaming */ 438 /* all substreams closed? if so, stop streaming */
457 if (!rt->playback.instance && !rt->capture.instance) { 439 if (!rt->playback.instance && !rt->capture.instance) {
458 usb6fire_pcm_stream_stop(rt); 440 usb6fire_pcm_stream_stop(rt);
459 rt->rate = -1; 441 rt->rate = ARRAY_SIZE(rates);
460 } 442 }
461 } 443 }
462 mutex_unlock(&rt->stream_mutex); 444 mutex_unlock(&rt->stream_mutex);
@@ -480,7 +462,6 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
480 struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); 462 struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
481 struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); 463 struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
482 struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; 464 struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
483 int i;
484 int ret; 465 int ret;
485 466
486 if (rt->panic) 467 if (rt->panic)
@@ -493,12 +474,10 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
493 sub->period_off = 0; 474 sub->period_off = 0;
494 475
495 if (rt->stream_state == STREAM_DISABLED) { 476 if (rt->stream_state == STREAM_DISABLED) {
496 for (i = 0; i < ARRAY_SIZE(rates); i++) 477 for (rt->rate = 0; rt->rate < ARRAY_SIZE(rates); rt->rate++)
497 if (alsa_rt->rate == rates[i]) { 478 if (alsa_rt->rate == rates[rt->rate])
498 rt->rate = i;
499 break; 479 break;
500 } 480 if (rt->rate == ARRAY_SIZE(rates)) {
501 if (i == ARRAY_SIZE(rates)) {
502 mutex_unlock(&rt->stream_mutex); 481 mutex_unlock(&rt->stream_mutex);
503 snd_printk("invalid rate %d in prepare.\n", 482 snd_printk("invalid rate %d in prepare.\n",
504 alsa_rt->rate); 483 alsa_rt->rate);
@@ -613,7 +592,7 @@ int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
613 592
614 rt->chip = chip; 593 rt->chip = chip;
615 rt->stream_state = STREAM_DISABLED; 594 rt->stream_state = STREAM_DISABLED;
616 rt->rate = -1; 595 rt->rate = ARRAY_SIZE(rates);
617 init_waitqueue_head(&rt->stream_wait_queue); 596 init_waitqueue_head(&rt->stream_wait_queue);
618 mutex_init(&rt->stream_mutex); 597 mutex_init(&rt->stream_mutex);
619 598