Index: forte.c
===================================================================
RCS file: /home/mkp/Repository/forte/forte.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -u -r1.51 -r1.52
--- forte.c	26 Aug 2002 18:10:41 -0000	1.51
+++ forte.c	24 Sep 2002 22:31:05 -0000	1.52
@@ -53,7 +53,7 @@
 #include <asm/hardirq.h>
 
 #define DRIVER_NAME	"forte"
-#define DRIVER_VERSION 	"$Id: forte.c,v 1.51 2002/08/26 18:10:41 mkp Exp $"
+#define DRIVER_VERSION 	"$Id: forte.c,v 1.52 2002/09/24 22:31:05 mkp Exp $"
 #define PFX 		DRIVER_NAME ": "
 
 #undef M_DEBUG
@@ -64,11 +64,18 @@
 #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 */
-#define FORTE_FMTS              (AFMT_U8 | AFMT_S16_LE)
+#ifdef FORTE_16BIT_ONLY
+  #define FORTE_FMTS		(AFMT_S16_LE)
+#else
+  #define FORTE_FMTS		(AFMT_U8 | AFMT_S16_LE)
+#endif
 
 /* Buffers */
 #define FORTE_MIN_FRAG_SIZE     256
@@ -462,49 +469,33 @@
 static int
 forte_channel_rate (struct forte_channel *channel, unsigned int rate)
 {
-	int new_rate, ret;
+	int new_rate;
 
 	if (!channel || !channel->iobase) 
 		return -EINVAL;
 
-	if (rate == 0 || channel->rate == rate) {
-		ret = channel->rate;
-		goto out;
-	}
-
-	if (rate > 48000)
-		rate = 48000;
-
-	if (rate < 5500)
-		rate = 5500;
-
-	switch (rate) {
-	case 5500:	new_rate =  0; break;
-	case 8000:	new_rate =  1; break;
-	case 9600:	new_rate =  2; break;
-	case 11025:	new_rate =  3; break;
-	case 16000:	new_rate =  4; break;
-	case 19200:	new_rate =  5; break;
-	case 22050:	new_rate =  6; break;
-	case 32000:	new_rate =  7; break;
-	case 38400:	new_rate =  8; break;
-	case 44100:	new_rate =  9; break;
-	case 48000:	new_rate = 10; break;
-
-	default:
-		DPRINTK ("Unsupported rate: %d", rate);
-		ret = -EINVAL;
-		goto out;
-	}
+	/* The FM801 only supports a handful of fixed frequencies.
+	 * We find the value closest to what userland requested.
+	 */
+	if      (rate <= 6250)  { rate = 5500;  new_rate =  0; }
+	else if (rate <= 8800)  { rate = 8000;  new_rate =  1; }
+	else if (rate <= 10312) { rate = 9600;  new_rate =  2; }
+	else if (rate <= 13512) { rate = 11025; new_rate =  3; }
+	else if (rate <= 17600) { rate = 16000; new_rate =  4; }
+	else if (rate <= 20625) { rate = 19200; new_rate =  5; }
+	else if (rate <= 27025) { rate = 22050; new_rate =  6; }
+	else if (rate <= 35200) { rate = 32000; new_rate =  7; }
+	else if (rate <= 41250) { rate = 38400; new_rate =  8; }
+	else if (rate <= 46050) { rate = 44100; new_rate =  9; }
+	else                    { rate = 48000; new_rate = 10; }
 
 	channel->ctrl &= ~FORTE_RATE_MASK;
 	channel->ctrl |= new_rate << FORTE_RATE_SHIFT;
-	channel->rate = ret = rate;
+	channel->rate = rate;
 
- out:
 	DPRINTK ("%s: %s rate = %d\n", __FUNCTION__, channel->name, rate);
 
-	return ret;
+	return rate;
 }
 
 
@@ -519,38 +510,32 @@
 static int
 forte_channel_format (struct forte_channel *channel, int format)
 {
-	int ret;
-
 	if (!channel || !channel->iobase) 
 		return -EINVAL;
 
-	DPRINTK ("%s: %s format = %d\n", __FUNCTION__, channel->name, format);
-
 	switch (format) {
 
 	case AFMT_QUERY:
-		ret = channel->format;
 		break;
 	
+#ifndef FORTE_16BIT_ONLY
 	case AFMT_U8:
 		channel->ctrl &= ~FORTE_16BIT;
-		channel->format = format;
-		ret = format;
+		channel->format = AFMT_U8;
 		break;
+#endif
 
 	case AFMT_S16_LE:
-		channel->ctrl |= FORTE_16BIT;
-		channel->format = format;
-		ret = format;
-		break;
-
 	default:
-		DPRINTK ("Unsupported audio format");
-		ret = -EINVAL;
+		channel->ctrl |= FORTE_16BIT;
+		channel->format = AFMT_S16_LE;
 		break;
 	}
 
-	return ret;
+	DPRINTK ("%s: %s want %d format, got %d\n", __FUNCTION__, channel->name, 
+		 format, channel->format);
+
+	return channel->format;
 }
 
 
@@ -669,14 +654,14 @@
 					     channel->buf_pages * PAGE_SIZE,
 					     &channel->buf_handle);
 
+	if (!channel->buf || !channel->buf_handle)
+		BUG();
+
 	page = virt_to_page (channel->buf);
 	
 	for (i = 0 ; i < channel->buf_pages ; i++)
 		mem_map_reserve (page++);
 
-	if (!channel->buf || !channel->buf_handle)
-		BUG();
-
 	/* Prep buffer registers */
 	outw (channel->frag_sz - 1, channel->iobase + FORTE_PLY_COUNT);
 	outl (channel->buf_handle, channel->iobase + FORTE_PLY_BUF1);
@@ -777,9 +762,9 @@
 
 	init_waitqueue_head (&channel->wait);
 
-	/* Defaults: 48kHz, 16-bit, mono */
+	/* Defaults: 48kHz, 16-bit, stereo */
 	forte_channel_reset (channel);
-	forte_channel_stereo (channel, 0);
+	forte_channel_stereo (channel, 1);
 	forte_channel_format (channel, AFMT_S16_LE);
 	forte_channel_rate (channel, 48000);
 	forte_channel_buffer (channel, FORTE_DEF_FRAG_SIZE, 
@@ -830,7 +815,6 @@
 		 unsigned long arg)
 {
 	int ival, ret, rval, rd, wr, count;
-	unsigned long flags;
 	struct forte_chip *chip;
 	struct audio_buf_info abi;
 	struct count_info cinfo;
@@ -1183,6 +1167,18 @@
 
 		return 0;
 		
+	case SOUND_PCM_READ_RATE:
+		DPRINTK ("%s: PCM_READ_RATE\n", __FUNCTION__);		
+		return put_user (chip->play.rate, (int *) arg);
+
+	case SOUND_PCM_READ_CHANNELS:
+		DPRINTK ("%s: PCM_READ_CHANNELS\n", __FUNCTION__);		
+		return put_user (chip->play.stereo, (int *) arg);
+
+	case SOUND_PCM_READ_BITS:
+		DPRINTK ("%s: PCM_READ_BITS\n", __FUNCTION__);		
+		return put_user (chip->play.format, (int *) arg);
+
 	default:
 		DPRINTK ("Unsupported ioctl: %x (%p)\n", cmd, (void *) arg);
 		break;
@@ -1200,7 +1196,6 @@
 forte_dsp_open (struct inode *inode, struct file *file)
 {
 	struct forte_chip *chip = forte; /* FIXME: HACK FROM HELL! */
-	struct forte_channel *channel;
 
 	if (down_interruptible (&chip->open_sem)) {
 		DPRINTK ("%s: returning -ERESTARTSYS\n", __FUNCTION__);
@@ -1209,7 +1204,7 @@
 
 	file->private_data = forte;
 
-	DPRINTK ("%s: chip @ %p\n", __FUNCTION__, file->private_data);
+	DPRINTK ("*****\n%s: chip @ %p\n", __FUNCTION__, file->private_data);
 
 	if (file->f_mode & FMODE_WRITE)
 		forte_channel_init (forte, &forte->play);
@@ -1252,7 +1247,6 @@
 		forte_channel_free (chip, &chip->rec);
 	}
 
- out:
 	up (&chip->open_sem);
 
 	return ret;
@@ -1484,7 +1478,7 @@
 {
 	struct forte_chip *chip;
 	struct forte_channel *channel;
-	unsigned int i = bytes, sz, ret;
+	unsigned int i = bytes, sz;
 	unsigned long flags;
 
 	if (ppos != &file->f_pos)
@@ -1746,7 +1740,7 @@
 
 	/* Init volume */
 	outw (0x0808, chip->iobase + FORTE_PCM_VOL);
-	outw (0x9f1f, chip->iobase + FORTE_FM_VOL);
+	outw (0x8808, chip->iobase + FORTE_FM_VOL);
 	outw (0x8808, chip->iobase + FORTE_I2S_VOL);
 
 	/* I2S control - I2S mode */
