Index: forte.c
===================================================================
RCS file: /home/mkp/Repository/forte/forte.c,v
retrieving revision 1.53
retrieving revision 1.55
diff -u -u -r1.53 -r1.55
--- forte.c	24 Sep 2002 23:31:01 -0000	1.53
+++ forte.c	2 Oct 2002 00:01:42 -0000	1.55
@@ -49,11 +49,13 @@
 #include <linux/ac97_codec.h>
 #include <linux/wrapper.h>
 
+#include <linux/proc_fs.h>
+
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 
 #define DRIVER_NAME	"forte"
-#define DRIVER_VERSION 	"$Id: forte.c,v 1.53 2002/09/24 23:31:01 mkp Exp $"
+#define DRIVER_VERSION 	"$Id: forte.c,v 1.55 2002/10/02 00:01:42 mkp Exp $"
 #define PFX 		DRIVER_NAME ": "
 
 #undef M_DEBUG
@@ -64,18 +66,11 @@
 #define DPRINTK(args...)
 #endif
 
-/* Codec I/F is buggy in 8-bit mode. Force chip to 16-bit only mode. */
-#define FORTE_16BIT_ONLY
-
 /* Card capabilities */
 #define FORTE_CAPS              (DSP_CAP_MMAP | DSP_CAP_TRIGGER)
 
 /* Supported audio formats */
-#ifdef FORTE_16BIT_ONLY
-  #define FORTE_FMTS		(AFMT_S16_LE)
-#else
-  #define FORTE_FMTS		(AFMT_U8 | AFMT_S16_LE)
-#endif
+#define FORTE_FMTS		(AFMT_U8 | AFMT_S16_LE)
 
 /* Buffers */
 #define FORTE_MIN_FRAG_SIZE     256
@@ -211,6 +206,10 @@
 };
 
 
+static int channels[] = { 2, 4, 6, };
+static int rates[]    = { 5500, 8000, 9600, 11025, 16000, 19200, 
+			  22050, 32000, 38400, 44100, 48000, };
+
 static struct forte_chip *forte;
 static int found;
 
@@ -518,12 +517,10 @@
 	case AFMT_QUERY:
 		break;
 	
-#ifndef FORTE_16BIT_ONLY
 	case AFMT_U8:
 		channel->ctrl &= ~FORTE_16BIT;
 		channel->format = AFMT_U8;
 		break;
-#endif
 
 	case AFMT_S16_LE:
 	default:
@@ -763,6 +760,7 @@
 	init_waitqueue_head (&channel->wait);
 
 	/* Defaults: 48kHz, 16-bit, stereo */
+	channel->ctrl = inw (channel->iobase + FORTE_PLY_CTRL);
 	forte_channel_reset (channel);
 	forte_channel_stereo (channel, 1);
 	forte_channel_format (channel, AFMT_S16_LE);
@@ -814,7 +812,7 @@
 forte_dsp_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
 		 unsigned long arg)
 {
-	int ival, ret, rval, rd, wr, count;
+	int ival=0, ret, rval=0, rd, wr, count;
 	struct forte_chip *chip;
 	struct audio_buf_info abi;
 	struct count_info cinfo;
@@ -1233,6 +1231,7 @@
 
 		spin_lock_irq (&chip->lock);
 
+		chip->play.ctrl |= FORTE_IMMED_STOP;
 		forte_channel_stop (&chip->play);
 		forte_channel_free (chip, &chip->play);
 
@@ -1243,8 +1242,13 @@
 		while (chip->rec.filled_frags > 0)
 			interruptible_sleep_on (&chip->rec.wait);
 
+		spin_lock_irq (&chip->lock);
+
+		chip->play.ctrl |= FORTE_IMMED_STOP;
 		forte_channel_stop (&chip->rec);
 		forte_channel_free (chip, &chip->rec);
+
+		spin_unlock_irq (&chip->lock);
 	}
 
 	up (&chip->open_sem);
@@ -1696,6 +1700,118 @@
 
 
 /**
+ * forte_proc_read:
+ */
+
+static int
+forte_proc_read (char *page, char **start, off_t off, int count, 
+		 int *eof, void *data)
+{
+	int i = 0, p_rate, p_chan, r_rate;
+	unsigned short p_reg, r_reg;
+
+	i += sprintf (page, "ForteMedia FM801 OSS Lite driver\n%s\n\n", 
+		      DRIVER_VERSION);
+
+	if (!forte->iobase)
+		return i;
+
+	p_rate = p_chan = -1;
+	p_reg  = inw (forte->iobase + FORTE_PLY_CTRL);
+	p_rate = (p_reg >> 8) & 15;
+	p_chan = (p_reg >> 12) & 3;
+
+ 	if (p_rate >= 0 || p_rate <= 10)
+		p_rate = rates[p_rate];
+
+	if (p_chan >= 0 || p_chan <= 2)
+		p_chan = channels[p_chan];
+
+	r_rate = -1;
+	r_reg  = inw (forte->iobase + FORTE_CAP_CTRL);
+	r_rate = (r_reg >> 8) & 15;
+
+ 	if (r_rate >= 0 || r_rate <= 10)
+		r_rate = rates[r_rate]; 
+
+	i += sprintf (page + i,
+		      "             Playback  Capture\n"
+		      "FIFO empty : %-3s       %-3s\n"
+		      "Buf1 Last  : %-3s       %-3s\n"
+		      "Buf2 Last  : %-3s       %-3s\n"
+		      "Started    : %-3s       %-3s\n"
+		      "Paused     : %-3s       %-3s\n"
+		      "Immed Stop : %-3s       %-3s\n"
+		      "Rate       : %-5d     %-5d\n"
+		      "Channels   : %-5d     -\n"
+		      "16-bit     : %-3s       %-3s\n"
+		      "Stereo     : %-3s       %-3s\n",
+		      p_reg & 1<<0  ? "yes" : "no",
+		      r_reg & 1<<0  ? "yes" : "no",
+		      p_reg & 1<<1  ? "yes" : "no",
+		      r_reg & 1<<1  ? "yes" : "no",
+		      p_reg & 1<<2  ? "yes" : "no",
+		      r_reg & 1<<2  ? "yes" : "no",
+		      p_reg & 1<<5  ? "yes" : "no",
+		      r_reg & 1<<5  ? "yes" : "no",
+		      p_reg & 1<<6  ? "yes" : "no",
+		      r_reg & 1<<6  ? "yes" : "no",
+		      p_reg & 1<<7  ? "yes" : "no",
+		      r_reg & 1<<7  ? "yes" : "no",
+		      p_rate, r_rate,
+		      p_chan,
+		      p_reg & 1<<14 ? "yes" : "no",
+		      r_reg & 1<<14 ? "yes" : "no",
+		      p_reg & 1<<15 ? "yes" : "no",
+		      r_reg & 1<<15 ? "yes" : "no");
+
+	return i;
+}
+
+
+/**
+ * forte_proc_init:
+ *
+ * Creates driver info entries in /proc
+ */
+
+static int __init 
+forte_proc_init (void)
+{
+	if (!proc_mkdir ("driver/forte", 0))
+		return -EIO;
+
+	if (!create_proc_read_entry ("driver/forte/chip", 0, 0, forte_proc_read, forte)) {
+		remove_proc_entry ("driver/forte", NULL);
+		return -EIO;
+	}
+
+	if (!create_proc_read_entry("driver/forte/ac97", 0, 0, ac97_read_proc, forte->ac97)) {
+		remove_proc_entry ("driver/forte/chip", NULL);
+		remove_proc_entry ("driver/forte", NULL);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+
+/**
+ * forte_proc_remove:
+ *
+ * Removes driver info entries in /proc
+ */
+
+static void
+forte_proc_remove (void)
+{
+	remove_proc_entry ("driver/forte/ac97", NULL);
+	remove_proc_entry ("driver/forte/chip", NULL);
+	remove_proc_entry ("driver/forte", NULL);	
+}
+
+
+/**
  * forte_chip_init:
  * @chip:	Chip instance to initialize
  *
@@ -1787,6 +1903,12 @@
 		return -1;
 	}
 
+	/* Register with /proc */
+	if (forte_proc_init()) {
+		printk (KERN_ERR PFX "couldn't add entries to /proc!\n");
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -1891,6 +2013,7 @@
 	outw (0x1f1f, chip->iobase + FORTE_FM_VOL);
 	outw (0x1f1f, chip->iobase + FORTE_I2S_VOL);
 
+	forte_proc_remove();
 	free_irq (chip->irq, chip);
 	release_region (chip->iobase, pci_resource_len (pci_dev, 0));
 
