All of lore.kernel.org
 help / color / mirror / Atom feed
* [parisc-linux] Recording with harmony
@ 2001-03-06 21:55 Matthieu Delahaye
  0 siblings, 0 replies; only message in thread
From: Matthieu Delahaye @ 2001-03-06 21:55 UTC (permalink / raw)
  To: parisc-linux; +Cc: t.simonnet

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

If you want to record your voice on your favorite workstation :)
-- 
Matthieu Delahaye
ESIEE Team
http://www.esiee.fr/puffin

[-- Attachment #2: harmony.diff --]
[-- Type: text/plain, Size: 9847 bytes --]

diff -Nru linux.old/drivers/sound/harmony.c linux.new/drivers/sound/harmony.c
--- linux.old/drivers/sound/harmony.c	Tue Mar  6 22:37:56 2001
+++ linux.new/drivers/sound/harmony.c	Tue Mar  6 22:41:27 2001
@@ -69,11 +69,13 @@
 	- modularisation, 
 	- cleanups
 
+2001-03-07: Matthieu Delahaye <delahaym@esiee.fr>
+        - added record functionality
+
 TODO:
 -----
 	- update/cleanup the above documentation
 	- fix CHECK_xxx functions -> use newer cache flushing functions 
-	- add recording functionality
 	- test if loading/unloading this driver as module works
 */
 
@@ -243,13 +245,21 @@
 	u8 sample_rate;
 	u8 stereo_select;	/* 1 = stereo, 0 = mono */
 	int format_initialized;
-	int suspended;
-	int blocked;
-	int done;
-	wait_queue_head_t wq;
-	int first_filled;	/* first buffer containing data (next to play) */
-	int nb_filled; 
+	int suspended_playing;
+	int suspended_recording;
 	
+	int blocked_playing;
+	int blocked_recording;
+	
+	int done;
+	wait_queue_head_t wq_play, wq_record;
+	int first_filled_play;	/* first buffer containing data (next to play) */
+	int nb_filled_play; 
+	int first_filled_record;
+	int nb_filled_record;
+	int playing;
+	int recording;
+		
 	int audio_open, mixer_open;
 	int dsp_unit, mixer_unit;
 };
@@ -262,13 +272,18 @@
 
 
 /* Until we have recording working, this is where we're putting the recording data. */
-static char graveyard[4096] 
-		__attribute__((aligned(4096)));
 
 static struct harmony_dev harmony;
 
-static unsigned char aligned_buf[MAX_BUFS * HARMONY_BUF_SIZE] 
-		__attribute__ ((aligned (HARMONY_BUF_SIZE))); 
+static unsigned char played_buf[MAX_BUFS * HARMONY_BUF_SIZE] 
+                     __attribute__ ((aligned (HARMONY_BUF_SIZE))); 
+static unsigned char recorded_buf[MAX_BUFS * HARMONY_BUF_SIZE]
+                     __attribute__ ((aligned (HARMONY_BUF_SIZE)));
+static char silent[HARMONY_BUF_SIZE] 
+		__attribute__((aligned(4096)));
+static char graveyard[HARMONY_BUF_SIZE] 
+		__attribute__((aligned(4096)));
+
 
 
 static void harmony_wait_CNTL(void)
@@ -347,12 +362,15 @@
 
 static int harmony_disable_interrupts(void) 
 {
+	harmony_wait_CNTL();
+	
 	gsc_writel(0, &(harmony.hpa->dstatus)); 
 	return 0;
 }
 
 static int harmony_enable_interrupts(void) 
 {
+	harmony_wait_CNTL();
 	gsc_writel(DSTATUS_IE, &(harmony.hpa->dstatus)); 
 	return 0;
 }
@@ -379,7 +397,7 @@
 		default:			silence_char = 0;
 	}
 
-	memset(aligned_buf+start, silence_char, length);
+	memset(played_buf+start, silence_char, length);
 	return 0;
 }
 
@@ -393,19 +411,28 @@
 	harmony.frames_so_far = 0;
 	harmony.done = 0; 
 	harmony.format_initialized = 0;
-	harmony.suspended = 0;
-	harmony.blocked = 0;
-	harmony.first_filled = 0;
-	harmony.nb_filled = 0;
-	init_waitqueue_head(&harmony.wq);
+	harmony.suspended_playing = 1;
+	harmony.blocked_playing = 0;
+	harmony.suspended_recording =1;
+	harmony.blocked_recording=0;
+	harmony.first_filled_play = 0;
+	harmony.nb_filled_play = 0;
+	harmony.first_filled_record = 0;
+	harmony.nb_filled_record = 0;
+	
+	init_waitqueue_head(&harmony.wq_play);
+	init_waitqueue_head(&harmony.wq_record);
 	
 	/* Start off in a balanced mode. */
 
+	harmony_set_control(HARMONY_DF_16BIT_LINEAR, HARMONY_SR_44KHZ, HARMONY_SS_STEREO);
+	harmony_update_control();
+
 	/* Clear out all the buffers and flush to cache */
-	harmony_silence(aligned_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS);
-	CHECK_WBACK_INV(aligned_buf, HARMONY_BUF_SIZE*MAX_BUFS);
+	harmony_silence(played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS);
+	CHECK_WBACK_INV(played_buf, HARMONY_BUF_SIZE*MAX_BUFS);
 	
-	harmony_mixer_mute_all();
+//	harmony_mixer_mute_all();
 
 	harmony_wait_CNTL();
 
@@ -434,15 +461,52 @@
 
 static ssize_t harmony_audio_read(struct file *file,
                                 char *buffer,
-                                size_t count,
+                                size_t size_count,
                                 loff_t *ppos)
 {
-	DPRINTK(KERN_ERR "%s: invalid read\n", __FUNCTION__);
-	return -ENODEV;
+	int total_count = (int) size_count;
+	int count = 0;
+	int buf_to_read;
+
+	while (count<total_count) {
+		/* Wait until we're out of control mode */
+		harmony_wait_CNTL();
+		
+		/* Figure out which buffer to fill in */
+		
+		if(harmony.nb_filled_record<=2) {
+			harmony.blocked_recording = 1;
+		        if(harmony.suspended_recording) {
+				harmony.suspended_recording=0;
+				harmony_enable_interrupts();
+			}
+							
+			interruptible_sleep_on(&(harmony.wq_record));
+			harmony.blocked_recording=0;
+		}
+		if(harmony.nb_filled_record<2) return -EBUSY;
+		
+		buf_to_read = harmony.first_filled_record;
+		
+		/* Figure out the size of the frame */
+	
+		/* Copy the page to an aligned buffer */
+		copy_to_user(buffer+count, 
+			     recorded_buf+(HARMONY_BUF_SIZE*buf_to_read), 
+			     HARMONY_BUF_SIZE);
+		
+		harmony.nb_filled_record--;
+		harmony.first_filled_record++;
+		harmony.first_filled_record%=MAX_BUFS;
+				
+		count += 4096;
+	}
+	return count;
 }
 
 
 
+
 /* Here is the place where we try to recognize file format.
    Sun/NeXT .au files began with the string .snd
    At offset 12 is specified the encoding.
@@ -531,12 +595,16 @@
 		harmony_wait_CNTL();
 
 		/* Figure out which buffer to fill in */
-		while (harmony.nb_filled+2 >= MAX_BUFS) {
-			harmony.blocked = 1;
-			interruptible_sleep_on(&(harmony.wq));
+		
+		if(harmony.nb_filled_play+2 >= MAX_BUFS) {
+			harmony.blocked_playing = 1;
+			interruptible_sleep_on(&(harmony.wq_play));
+			harmony.blocked_playing=0;
 		}
-	
-		buf_to_fill = (harmony.first_filled+harmony.nb_filled) % MAX_BUFS;
+		if(harmony.nb_filled_play+2 >= MAX_BUFS) return -EBUSY;
+		
+		
+		buf_to_fill = (harmony.first_filled_play+harmony.nb_filled_play) % MAX_BUFS;
 
 		/* Figure out the size of the frame */
 		if ((total_count-count) > HARMONY_BUF_SIZE) {
@@ -545,33 +613,26 @@
 			frame_size = total_count - count;
 			/* Clear out the buffer, since there we'll only be 
 			   overlaying part of the old buffer with the new one */
-			harmony_silence(aligned_buf, HARMONY_BUF_SIZE*buf_to_fill, 
+			harmony_silence(played_buf, HARMONY_BUF_SIZE*buf_to_fill, 
 					HARMONY_BUF_SIZE);
 		}
 
 		/* Copy the page to an aligned buffer */
-		copy_from_user(aligned_buf+(HARMONY_BUF_SIZE*buf_to_fill), 
+		copy_from_user(played_buf+(HARMONY_BUF_SIZE*buf_to_fill), 
 				buffer+count, frame_size);
 	
-		harmony.nb_filled++;
+		harmony.nb_filled_play++;
 
-		CHECK_WBACK_INV(aligned_buf, HARMONY_BUF_SIZE*MAX_BUFS);
+		CHECK_WBACK_INV(played_buf, HARMONY_BUF_SIZE*MAX_BUFS);
 		
 		harmony.done = 0;
 		count += frame_size;
 
-		if (harmony.frames_so_far == 1) {
-			harmony_mixer_unmute();
-		   	harmony_enable_interrupts();
-		}
-
-		if (harmony.suspended) {
-			harmony.suspended = 0;
+		if (harmony.suspended_playing && (harmony.nb_filled_play>=4)) {
 			harmony_enable_interrupts();
 		}
-		
-		harmony.frames_so_far++;
 	}
+	
 	return count;
 }
 
@@ -678,37 +739,63 @@
 
 	/* Setup the hpa */
 	hpa = ((struct harmony_dev *)dev)->hpa;
+	harmony_wait_CNTL();
 	
 	/* Read dstatus and pcuradd (the current address) */
 	dstatus = gsc_readl(&hpa->dstatus);
 	
 	/* Turn off interrupts */
 	harmony_disable_interrupts();
-	dstatus = gsc_readl(&hpa->dstatus);
 	
 	/* Check if this is a request to get the next play buffer */
 	if (dstatus & DSTATUS_PN) {
-		if (!harmony.nb_filled) {
-			harmony.suspended = 1;
+		if (!harmony.nb_filled_play) {
+			harmony.suspended_playing = 1;
+			harmony_silence(silent, 0,HARMONY_BUF_SIZE);
+			gsc_writel(__pa(silent), &hpa->pnxtadd);
+						
+			if(!harmony.suspended_recording) {
+				harmony_enable_interrupts();
+			} 
 		} else {
-			gsc_writel(__pa(aligned_buf+(HARMONY_BUF_SIZE*harmony.first_filled)), 
+			harmony.suspended_playing=0;
+			gsc_writel(__pa(played_buf+(HARMONY_BUF_SIZE*harmony.first_filled_play)), 
 					&hpa->pnxtadd);
-			harmony.first_filled++;
-			harmony.first_filled %= MAX_BUFS;
-			harmony.nb_filled--;
-			harmony_enable_interrupts();
+			harmony.first_filled_play++;
+			harmony.first_filled_play %= MAX_BUFS;
+			harmony.nb_filled_play--;
+			
+		       	harmony_enable_interrupts();
 		}
-
-		if (harmony.blocked) {
-			wake_up_interruptible(&(harmony.wq));
-			harmony.blocked = 0;
+		if (harmony.blocked_playing) {
+			wake_up_interruptible(&(harmony.wq_play));
 		}
 	}
 	
 	/* Check if we're being asked to fill in a recording buffer */
 	if (dstatus & DSTATUS_RN) {
-		/* Not supported yet */
-		gsc_writel(__pa(graveyard), &hpa->rnxtadd);
+		if((harmony.nb_filled_record+2>=MAX_BUFS) || harmony.suspended_recording)
+		{
+			harmony.nb_filled_record=0;
+			harmony.first_filled_record=0;
+			harmony.suspended_recording = 1;
+			gsc_writel(__pa(graveyard), &hpa->rnxtadd);
+			if(!harmony.suspended_playing)
+				harmony_enable_interrupts();
+		} else {
+			int buf_to_fill;
+			buf_to_fill=(harmony.first_filled_record+harmony.nb_filled_record)%MAX_BUFS;
+			CHECK_WBACK_INV(recorded_buf+(HARMONY_BUF_SIZE*buf_to_fill), HARMONY_BUF_SIZE);
+			gsc_writel(__pa(recorded_buf+(HARMONY_BUF_SIZE*(buf_to_fill))),&hpa->rnxtadd);
+			harmony.nb_filled_record++;
+			harmony_enable_interrupts();
+		}
+
+		if (harmony.blocked_recording && 
+		    harmony.nb_filled_record>3) {
+						
+			wake_up_interruptible(&(harmony.wq_record));
+		}
 	}
 }
 
@@ -738,13 +825,12 @@
 		return -EFAULT;
 	}
 	
-	harmony_set_control(HARMONY_DF_16BIT_LINEAR, HARMONY_SR_22KHZ, HARMONY_SS_MONO);
-
+	
 	/* Clear the buffers so you don't end up with crap in the buffers. */ 
-	harmony_silence(aligned_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS);
+	harmony_silence(played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS);
 
 	/* Make sure this makes it to cache */
-	CHECK_WBACK_INV(aligned_buf, HARMONY_BUF_SIZE*MAX_BUFS);
+	CHECK_WBACK_INV(played_buf, HARMONY_BUF_SIZE*MAX_BUFS);
 
 	/* Wait around until we're out of control mode */
 	harmony_wait_CNTL();

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2001-03-06 21:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-03-06 21:55 [parisc-linux] Recording with harmony Matthieu Delahaye

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.