NEC VR5701 support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Source: MontaVista Software, Inc.
MR: 14926
Type: Defect Fix
Disposition: needs submitting to linuxmips-embedded mailing list
Signed-off-by: Aleksey Makarov <makarov@xxxxxxxxxxxxx>
Description:
    Fixes bug with sound on 11025 and 22050 rates on NEC vr5701.

Index: linux-2.6.10/include/linux/lsppatchlevel.h
===================================================================
--- linux-2.6.10.orig/include/linux/lsppatchlevel.h
+++ linux-2.6.10/include/linux/lsppatchlevel.h
@@ -6,4 +6,4 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
-#define LSP_PATCH_LEVEL "11"
+#define LSP_PATCH_LEVEL "12"
Index: linux-2.6.10/mvl_patches/pro-0012.c
===================================================================
--- /dev/null
+++ linux-2.6.10/mvl_patches/pro-0012.c
@@ -0,0 +1,16 @@
+/*
+ * Author: MontaVista Software, Inc. <source@xxxxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/init.h>
+#include <linux/mvl_patch.h>
+
+static __init int regpatch(void)
+{
+        return mvl_register_patch(12);
+}
+module_init(regpatch);
Index: linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.c
===================================================================
--- linux-2.6.10.orig/sound/pci/vr5701/nec_vr5701_sg2.c
+++ linux-2.6.10/sound/pci/vr5701/nec_vr5701_sg2.c
@@ -89,6 +89,28 @@ static int snd_vr5701_ac97(vr5701_t *chi
 	return snd_ac97_mixer(bus, &ac97, &chip->ac97);
 }
 
+static int set_constraints(snd_pcm_substream_t *substream)
+{
+	int err;
+
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+			SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x10);
+	if( err < 0 )
+		return err;
+
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+			SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 0x40);
+	if( err < 0 )
+		return err;
+
+	err = snd_pcm_hw_constraint_list(substream->runtime, 0,
+			SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
+	if( err < 0 )
+		return err;
+
+	return 0;
+}
+
 /* open callback */
 static int snd_vr5701_playback_open(snd_pcm_substream_t *substream)
 {
@@ -97,8 +119,7 @@ static int snd_vr5701_playback_open(snd_
 	substream->runtime->hw = snd_vr5701_playback_hw;
 	chip->next_playback = 0;
 
-	return (snd_pcm_hw_constraint_list(substream->runtime, 0,
-		SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0); 
+	return set_constraints( substream );
 }
 
 
@@ -110,8 +131,7 @@ static int snd_vr5701_capture_open(snd_p
 	substream->runtime->hw = snd_vr5701_capture_hw;
 	chip->next_capture = 0;
 
-	return (snd_pcm_hw_constraint_list(substream->runtime, 0,
-		SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
+	return set_constraints( substream );
 }
 
 /* hw_params callback */
@@ -215,6 +235,42 @@ static int snd_vr5701_capture_close(snd_
 	return 0;
 }
 
+static inline void playback_next_position(snd_pcm_substream_t *substream, vr5701_t *chip)
+{
+	chip->next_playback = chip->next_playback ? 0 :
+		frames_to_bytes(substream->runtime, substream->runtime->period_size);
+}
+
+static inline void capture_next_position(snd_pcm_substream_t *substream, vr5701_t *chip)
+{
+	chip->next_capture = chip->next_capture ? 0 :
+		frames_to_bytes(substream->runtime, substream->runtime->period_size);
+}
+
+static inline void playback_setup_next(snd_pcm_substream_t *substream, vr5701_t *chip)
+{
+	u32 ch2_offset = (substream->runtime->channels == 1) ? 0 :
+		substream->runtime->dma_bytes/2;
+
+	outl(substream->runtime->dma_addr + chip->next_playback,
+			chip->port + vr5701_DAC1_BADDR);
+	outl(substream->runtime->dma_addr + chip->next_playback + ch2_offset,
+			chip->port + vr5701_DAC2_BADDR);
+}
+
+static inline void capture_setup_next(snd_pcm_substream_t *substream, vr5701_t *chip)
+{
+	if (substream->runtime->channels == 1) {
+		outl(substream->runtime->dma_addr + chip->next_capture,
+					chip->port + vr5701_ADC1_BADDR);
+	} else {
+		outl(substream->runtime->dma_addr+ chip->next_capture,
+					chip->port + vr5701_ADC1_BADDR);
+		outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
+				+ chip->next_capture, chip->port + vr5701_ADC2_BADDR);
+	}
+}
+
 static void vr5701_dma_start_playback(snd_pcm_substream_t *substream)
 {
 	u32 temp;
@@ -230,18 +286,7 @@ static void vr5701_dma_start_playback(sn
 	temp |= vr5701_INT_MASK_DAC1END | vr5701_INT_MASK_DAC2END;
 	outl(temp, chip->port + vr5701_INT_MASK);
 
-	/* setup dma base addr */
-	if (substream->runtime->channels == 1) {
-		outl(substream->runtime->dma_addr + chip->next_playback, 
-						chip->port + vr5701_DAC1_BADDR);
-		outl(substream->runtime->dma_addr + chip->next_playback, 
-						chip->port + vr5701_DAC2_BADDR);
-	} else {
-		outl(substream->runtime->dma_addr + chip->next_playback, 
-						chip->port + vr5701_DAC1_BADDR);
-		outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2 
-				+ chip->next_playback, chip->port + vr5701_DAC2_BADDR);
-	}
+	playback_setup_next( substream, chip );
 
 	/* set dma length, in the unit of 0x10 bytes */
 	period_size = (frames_to_bytes(substream->runtime, 
@@ -258,27 +303,10 @@ static void vr5701_dma_start_playback(sn
 	temp |= (vr5701_CTRL_DAC1ENB | vr5701_CTRL_DAC2ENB);
 	outl(temp, chip->port + vr5701_CTRL);
 
-	/* it is time to setup next dma transfer */
-	temp = chip->next_playback + frames_to_bytes(substream->runtime, 
-			substream->runtime->period_size);
+	playback_next_position( substream, chip );
+	playback_setup_next( substream, chip );
+	playback_next_position( substream, chip );
 
-	if (substream->runtime->channels == 1) {
-		if (temp >= substream->runtime->dma_bytes) {
-			temp = 0;
-		}
-		outl(substream->runtime->dma_addr + temp, 
-				chip->port + vr5701_DAC1_BADDR);
-		outl(substream->runtime->dma_addr + temp, 
-				chip->port + vr5701_DAC2_BADDR);
-	} else {
-		if (temp >= substream->runtime->dma_bytes/2) {
-			temp = 0;
-		}
-		outl(substream->runtime->dma_addr + temp, 
-				chip->port + vr5701_DAC1_BADDR);
-		outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
-						+ temp, chip->port + vr5701_DAC2_BADDR);
-	}
 	return ;
 }
 
@@ -297,16 +325,7 @@ static void vr5701_dma_start_capture(snd
 	temp |= vr5701_INT_MASK_ADC1END | vr5701_INT_MASK_ADC2END;
 	outl(temp, chip->port + vr5701_INT_MASK);
 
-	/* setup dma base addr */
-	if (substream->runtime->channels == 1) {
-		outl(substream->runtime->dma_addr + chip->next_capture, 
-					chip->port + vr5701_ADC1_BADDR);
-	} else {
-		outl(substream->runtime->dma_addr+ chip->next_capture, 
-					chip->port + vr5701_ADC1_BADDR);
-		outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2 
-				+ chip->next_capture, chip->port + vr5701_ADC2_BADDR);
-	}
+	capture_setup_next( substream, chip );
 
 	/* set dma length, in the unit of 0x10 bytes */
 	period_size = (frames_to_bytes(substream->runtime, 
@@ -331,24 +350,10 @@ static void vr5701_dma_start_capture(snd
 	temp |= (vr5701_CTRL_ADC1ENB | vr5701_CTRL_ADC2ENB);
 	outl(temp, chip->port + vr5701_CTRL);
 
-	/* it is time to setup next dma transfer */
-	temp = chip->next_capture + frames_to_bytes(substream->runtime, 
-			substream->runtime->period_size);
-	if (substream->runtime->channels == 1) {
-		if (temp >= substream->runtime->dma_bytes) {
-			temp = 0;
-		}
-		outl(substream->runtime->dma_addr + temp, 
-				chip->port + vr5701_ADC1_BADDR);
-	} else {
-		if (temp >= substream->runtime->dma_bytes/2) {
-			temp = 0;
-		}
-		outl(substream->runtime->dma_addr + temp, 
-				chip->port + vr5701_ADC1_BADDR);
-		outl(substream->runtime->dma_addr + substream->runtime->dma_bytes/2
-						+ temp,	chip->port + vr5701_ADC2_BADDR);
-	}
+	capture_next_position( substream, chip );
+	capture_setup_next( substream, chip );
+	capture_next_position( substream, chip );
+
 	return ;
 }
 
@@ -474,91 +479,20 @@ static int snd_vr5701_dev_free(snd_devic
 	vr5701_t *chip = device->device_data;
 	return snd_vr5701_free(chip);
 }
-static void vr5701_ac97_adc_interrupt(struct snd_vr5701 *chip)
+static inline void vr5701_ac97_adc_interrupt(struct snd_vr5701 *chip)
 {
-	unsigned temp;
-
-	/* set the base addr for next DMA transfer */
-	temp = chip->next_capture + 2*(frames_to_bytes(chip->substream[CAPTURE]->runtime, 
-			chip->substream[CAPTURE]->runtime->period_size));
-	if (chip->substream[CAPTURE]->runtime->channels == 1) {
-		if (temp >= chip->substream[CAPTURE]->runtime->dma_bytes) {
-			temp -= chip->substream[CAPTURE]->runtime->dma_bytes;
-		}
-	} else {
-		if (temp >= chip->substream[CAPTURE]->runtime->dma_bytes/2) {
-			temp -= chip->substream[CAPTURE]->runtime->dma_bytes/2;
-		}
-	}
-
-	if (chip->substream[CAPTURE]->runtime->channels == 1) {
-		outl(chip->substream[CAPTURE]->runtime->dma_addr 
-				+ temp, chip->port + vr5701_ADC1_BADDR);
-	} else {
-		outl(chip->substream[CAPTURE]->runtime->dma_addr 
-				+ temp, chip->port + vr5701_ADC1_BADDR);
-		outl(chip->substream[CAPTURE]->runtime->dma_addr 
-		+ chip->substream[CAPTURE]->runtime->dma_bytes/2+ temp, 
-						chip->port + vr5701_ADC2_BADDR);
-	}
-
-	/* adjust next pointer */
-	chip->next_capture += frames_to_bytes(chip->substream[CAPTURE]->runtime, 
-					chip->substream[CAPTURE]->runtime->period_size);
-	if (chip->substream[CAPTURE]->runtime->channels == 1) {
-		if (chip->next_capture >= chip->substream[CAPTURE]->runtime->dma_bytes){
-			chip->next_capture = 0;
-		}
-	} else {
-		if (chip->next_capture >= chip->substream[CAPTURE]->runtime->dma_bytes/2){
-			chip->next_capture = 0;
-		}
-	}
+	snd_pcm_substream_t * substream = chip->substream[CAPTURE];
+	capture_setup_next( substream, chip );
+	capture_next_position( substream, chip );
 }
 
-static void vr5701_ac97_dac_interrupt(struct snd_vr5701 *chip)
+static inline void vr5701_ac97_dac_interrupt(struct snd_vr5701 *chip)
 {
-	unsigned temp;
-
-	/* let us set for next next DMA transfer */
-	temp = chip->next_playback + 2*(frames_to_bytes(chip->substream[PLAYBACK]->runtime, 
-			chip->substream[PLAYBACK]->runtime->period_size));
-	if (chip->substream[PLAYBACK]->runtime->channels == 1) {
-		if (temp >= chip->substream[PLAYBACK]->runtime->dma_bytes) {
-			temp -= chip->substream[PLAYBACK]->runtime->dma_bytes;
-		}
-	} else {
-		if (temp >= chip->substream[PLAYBACK]->runtime->dma_bytes/2) {
-			temp -= chip->substream[PLAYBACK]->runtime->dma_bytes/2;
-		}
-	}
-
-	if (chip->substream[PLAYBACK]->runtime->channels == 1) {
-		outl(chip->substream[PLAYBACK]->runtime->dma_addr 
-				+ temp, chip->port + vr5701_DAC1_BADDR);
-		outl(chip->substream[PLAYBACK]->runtime->dma_addr 
-				+ temp, chip->port + vr5701_DAC2_BADDR);
-	} else {
-		outl(chip->substream[PLAYBACK]->runtime->dma_addr 
-				+ temp, chip->port + vr5701_DAC1_BADDR);
-		outl(chip->substream[PLAYBACK]->runtime->dma_addr 
-			+ chip->substream[PLAYBACK]->runtime->dma_bytes/2
-				+ temp,	chip->port + vr5701_DAC2_BADDR);
-	}
-
-	/* adjust next pointer */
-	chip->next_playback += frames_to_bytes(chip->substream[PLAYBACK]->runtime, 
-					chip->substream[PLAYBACK]->runtime->period_size);
-	if (chip->substream[PLAYBACK]->runtime->channels == 1) {
-		if (chip->next_playback >= chip->substream[PLAYBACK]->runtime->dma_bytes){
-			chip->next_playback = 0;
-		}
-	} else {
-		if (chip->next_playback >= chip->substream[PLAYBACK]->runtime->dma_bytes/2){
-			chip->next_playback = 0;
-		}
-	}
+	snd_pcm_substream_t * substream = chip->substream[PLAYBACK];
+	playback_setup_next( substream, chip );
+	playback_next_position( substream, chip );
 }
+
 static irqreturn_t snd_vr5701_interrupt(int irq, void *dev_id,
                                           struct pt_regs *regs)
 {

[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux