Stefano D'Angelo wrote:
> urb->transfer_dma = runtime->dma_addr;
This will always play the data at the beginning of the buffer.
fixed
> urb->transfer_buffer = usb_buffer_alloc (urb->dev,
> LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT * 2, GFP_KERNEL, &urb->transfer_dma);
This buffer should be allocated when the URB is allocated.
fixed
> memcpy (urb->transfer_buffer, runtime->dma_area + chip->playback_pos *
> 2, LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT * 2);
I hope the buffer size is a multiple of PACKET_SIZE_OUT * 2.
it is
> urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
Why the NO_TRANSFER_DMA_MAP? You shouldn't need to do such
optimizations in the first version of the driver.
ok
> snd_pcm_period_elapsed (substream);
What is the period size?
period size is 96 = LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT * 2 (double buffering) / 2 (16 bit data), so everytime an urb is sent a period is elapsed.
Here is how I'm doing right now but I still got the same beep for everything I play (when I used the copy () callback it kind of worked, is perphaps possible that the soundcard doesn't support dma transfers?):
static void snd_line6_tp_ux1_complete_playback_transfer (struct urb* urb,
struct pt_regs* regs)
{
snd_pcm_substream_t *substream = (snd_pcm_substream_t *)(urb->context);
struct snd_line6_tp_ux1 *chip = snd_pcm_substream_chip (substream);
snd_pcm_runtime_t *runtime = substream->runtime;
chip->playback_pos += LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT * 2 / 2;
if (chip->playback_pos == runtime->buffer_size) {
chip->playback_pos -= runtime->buffer_size;
if (chip->playback_pos == runtime->buffer_size) {
chip->playback_pos -= runtime->buffer_size;
}
memcpy (urb->transfer_buffer, runtime->dma_area + chip->playback_pos * 2, LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT * 2);
snd_pcm_period_elapsed (substream);
usb_submit_urb (urb, GFP_ATOMIC);
}
}
static int snd_line6_tp_ux1_pcm_trigger (snd_pcm_substream_t *substream,
int cmd)
int cmd)
{
struct snd_line6_tp_ux1 *chip = snd_pcm_substream_chip (substream);
snd_pcm_runtime_t *runtime = substream->runtime;
static struct urb* urb;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
urb = usb_alloc_urb (2, GFP_ATOMIC);
urb->dev = chip->dev;
urb->pipe = usb_sndisocpipe (urb->dev, 1);
urb->complete = snd_line6_tp_ux1_complete_playback_transfer;
urb->context = substream;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
urb = usb_alloc_urb (2, GFP_ATOMIC);
urb->dev = chip->dev;
urb->pipe = usb_sndisocpipe (urb->dev, 1);
urb->complete = snd_line6_tp_ux1_complete_playback_transfer;
urb->context = substream;
urb->transfer_dma = runtime->dma_addr;
urb->transfer_buffer = usb_buffer_alloc (urb->dev,
LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT * 2, GFP_ATOMIC,
&urb->transfer_dma);
memcpy (urb->transfer_buffer, runtime->dma_area,
LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT * 2);
&urb->transfer_dma);
memcpy (urb->transfer_buffer, runtime->dma_area,
LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT * 2);
urb->transfer_flags = URB_ISO_ASAP; // | URB_NO_TRANSFER_DMA_MAP;
urb->interval = 1;
urb->number_of_packets = 2;
urb->iso_frame_desc[0].offset = 0;
urb->iso_frame_desc[0].length = urb->iso_frame_desc[1].offset =
urb->iso_frame_desc[1].length =
LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT;
chip->playback_pos = 0;
usb_submit_urb (urb, GFP_KERNEL);
break;
case SNDRV_PCM_TRIGGER_STOP:
usb_buffer_free (chip->dev,
urb->number_of_packets = 2;
urb->iso_frame_desc[0].offset = 0;
urb->iso_frame_desc[0].length = urb->iso_frame_desc[1].offset =
urb->iso_frame_desc[1].length =
LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT;
chip->playback_pos = 0;
usb_submit_urb (urb, GFP_KERNEL);
break;
case SNDRV_PCM_TRIGGER_STOP:
usb_buffer_free (chip->dev,
LINE6_TP_UX1_48000_16_PACKET_SIZE_OUT * 2,
usb_free_urb (urb);
break;
default:
return -EINVAL;
break;
}
return 0;
}
Thanks,
Stefano
_______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.sourceforge.net/lists/listinfo/alsa-devel