All of lore.kernel.org
 help / color / mirror / Atom feed
* tm6000 audio buffer
@ 2010-06-04 19:39 Luis Henrique Fagundes
  2010-06-05  0:28 ` Mauro Carvalho Chehab
  2010-06-06 15:19 ` Mauro Carvalho Chehab
  0 siblings, 2 replies; 4+ messages in thread
From: Luis Henrique Fagundes @ 2010-06-04 19:39 UTC (permalink / raw)
  To: Linux Media Mailing List, Mauro Carvalho Chehab

[-- Attachment #1: Type: text/plain, Size: 837 bytes --]

Hi,

I'm sending a patch that hypothetically would allocate a memory buffer
for the audio and copy the data from urb to buffer. It doesn't work,
so I'm not putting a [PATCH] in subject and send it just for feedback.
Am I going on the right way of implementing this? The patch was made
against the mercurial version at http://linuxtv.org/hg/v4l-dvb.

I can see the audio packets at tm6000-video.c. Mauro said that the urb
audio packets had just 4 bytes of relevant data, 2 for each channel,
but the audio buffer has 128Kb and I see too few packets. Anyway, the
tm6000_audio_isocirq function receives the size of the packet and now
is copying everything to the buffer, I guess next step will be to find
what is relevant in this stream and make sure I have all packets here.

I haven't applied all the recent patches from Stefan yet.

Luis

[-- Attachment #2: audio_buffer_patch --]
[-- Type: application/octet-stream, Size: 6425 bytes --]

diff -r 304cfde05b3f linux/drivers/staging/tm6000/tm6000-alsa.c
--- a/linux/drivers/staging/tm6000/tm6000-alsa.c	Tue May 25 23:50:51 2010 -0400
+++ b/linux/drivers/staging/tm6000/tm6000-alsa.c	Fri Jun 04 16:14:09 2010 -0300
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/usb.h>
+#include <linux/vmalloc.h>
 
 #include <asm/delay.h>
 #include <sound/core.h>
@@ -182,6 +183,69 @@
 	.buffer_bytes_max = (1024*1024),
 };
 
+static void tm6000_audio_isocirq(struct tm6000_audio *adev, u8 *cp, int actual_length) {
+        
+	unsigned int             oldptr;
+	unsigned int             stride;
+	struct snd_pcm_substream *substream;
+	struct snd_pcm_runtime   *runtime;
+
+        cp += 4;
+
+        int period_elapsed = 0;
+
+        //actual_length = 4;
+
+        if (adev->capture_pcm_substream) {
+                substream = adev->capture_pcm_substream;
+                runtime = substream->runtime;
+                stride = runtime->frame_bits >> 3; // 4
+
+                int length = actual_length / stride;
+
+                if (!length)
+                        return; 
+                
+                oldptr = adev->hwptr_done_capture;
+                if (oldptr + length >= runtime->buffer_size) {
+                        unsigned int cnt =
+                                runtime->buffer_size - oldptr;
+                        memcpy(runtime->dma_area + oldptr * stride, cp,
+                               cnt * stride);
+                        memcpy(runtime->dma_area, cp + cnt * stride,
+                               length * stride - cnt * stride);
+                } else {
+                        memcpy(runtime->dma_area + oldptr * stride, cp,
+                               length * stride);
+                }
+                
+                snd_pcm_stream_lock(substream);
+
+                adev->hwptr_done_capture += length;
+                if (adev->hwptr_done_capture >=
+                    runtime->buffer_size)
+                        adev->hwptr_done_capture -=
+                                runtime->buffer_size;
+                
+                adev->capture_transfer_done += length;
+                if (adev->capture_transfer_done >=
+                    runtime->period_size) {
+                        adev->capture_transfer_done -=
+                                runtime->period_size;
+                        period_elapsed = 1;
+                }
+
+                snd_pcm_stream_unlock(substream);
+
+                if (period_elapsed) {
+			snd_pcm_period_elapsed(substream);
+                }
+
+	}
+
+	return;
+}
+
 /*
  * audio pcm capture open callback
  */
@@ -190,6 +254,10 @@
 	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int err;
+
+        chip->core->adev.capture_pcm_substream = substream;
+        chip->core->adev.initialized = 1;
+        chip->core->audio_isoc_callback = tm6000_audio_isocirq;
 
 	err = snd_pcm_hw_constraint_pow2(runtime, 0,
 					 SNDRV_PCM_HW_PARAM_PERIODS);
@@ -211,6 +281,25 @@
  */
 static int snd_tm6000_close(struct snd_pcm_substream *substream)
 {
+        struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+        chip->core->adev.initialized = 0;
+        return 0;
+}
+
+/* allocate virtual buffer; may be called more than once */
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size)
+{
+	struct snd_pcm_runtime *runtime = subs->runtime;
+	if (runtime->dma_area) {
+		if (runtime->dma_bytes >= size)
+			return 0; /* already large enough */
+		vfree(runtime->dma_area);
+	}
+        printk("alloc %d\n", size);
+	runtime->dma_area = vmalloc_user(size);
+	if (!runtime->dma_area)
+		return -ENOMEM;
+	runtime->dma_bytes = size;
 	return 0;
 }
 
@@ -220,6 +309,7 @@
 static int snd_tm6000_hw_params(struct snd_pcm_substream *substream,
 			      struct snd_pcm_hw_params *hw_params)
 {
+        int ret;
 	struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
 
 	if (substream->runtime->dma_area) {
@@ -236,6 +326,9 @@
 	dprintk(1, "Setting buffer\n");
 
 	/* FIXME: Allocate buffer for audio */
+
+	ret = snd_pcm_alloc_vmalloc_buffer(substream,
+				params_buffer_bytes(hw_params));
 
 #if 0
 	substream->runtime->dma_area = chip->dma_risc->vmalloc;
@@ -260,11 +353,18 @@
 	return 0;
 }
 
+
+
 /*
  * prepare callback
  */
 static int snd_tm6000_prepare(struct snd_pcm_substream *substream)
 {
+        struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+        chip->core->adev.capture_transfer_done = 0;
+        chip->core->adev.hwptr_done_capture = 0;
+
 	return 0;
 }
 
diff -r 304cfde05b3f linux/drivers/staging/tm6000/tm6000-video.c
--- a/linux/drivers/staging/tm6000/tm6000-video.c	Tue May 25 23:50:51 2010 -0400
+++ b/linux/drivers/staging/tm6000/tm6000-video.c	Fri Jun 04 16:14:09 2010 -0300
@@ -320,9 +320,13 @@
 		case TM6000_URB_MSG_PTS:
 			break;
 		case TM6000_URB_MSG_AUDIO:
-/* Need some code to process audio */
-printk ("%ld: cmd=%s, size=%d\n", jiffies,
-				tm6000_msg_type[cmd],size);
+                        if (dev->adev.initialized) {
+                                dev->audio_isoc_callback(&dev->adev, *ptr, cpysize);
+                        }
+
+                        break;
+
+		case TM6000_URB_MSG_VBI:
 			break;
 		default:
 			dprintk (dev, V4L2_DEBUG_ISOC, "cmd=%s, size=%d\n",
diff -r 304cfde05b3f linux/drivers/staging/tm6000/tm6000.h
--- a/linux/drivers/staging/tm6000/tm6000.h	Tue May 25 23:50:51 2010 -0400
+++ b/linux/drivers/staging/tm6000/tm6000.h	Fri Jun 04 16:14:09 2010 -0300
@@ -148,6 +148,15 @@
 	unsigned			maxsize;
 };
 
+struct tm6000_audio {
+      struct snd_pcm_substream   *capture_pcm_substream;
+      unsigned int capture_transfer_done;
+      unsigned int hwptr_done_capture;
+      int initialized;
+};
+
+typedef void (*tm6000_audio_complete_t)(struct tm6000_audio *adev, u8 *ptr, int len);
+
 struct tm6000_core {
 	/* generic device properties */
 	char				name[30];	/* name (including minor) of the device */
@@ -168,6 +177,11 @@
 	int				tuner_addr;		/* tuner address */
 
 	struct tm6000_gpio		gpio;
+        
+        /* Audio device */
+        struct tm6000_audio             adev;
+        tm6000_audio_complete_t         audio_isoc_callback;
+
 
 	/* Demodulator configuration */
 	int				demod_addr;	/* demodulator address */

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-06-07 19:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-04 19:39 tm6000 audio buffer Luis Henrique Fagundes
2010-06-05  0:28 ` Mauro Carvalho Chehab
2010-06-06 15:19 ` Mauro Carvalho Chehab
2010-06-07 19:03   ` Stefan Ringel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.