Beispiel #1
0
static void
do_dma (struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode)
{
  unsigned char   temp;

  if (dma_chan != SSCAPE_DMA_A)
    {
      printk ("SSCAPE: Tried to use DMA channel  != A. Why?\n");
      return;
    }

  audio_devs[devc->my_audiodev]->flags &= ~DMA_AUTOMODE;
  DMAbuf_start_dma (devc->my_audiodev,
		    buf,
		    blk_size, mode);
  audio_devs[devc->my_audiodev]->flags |= DMA_AUTOMODE;

  temp = devc->dma << 4;	/* Setup DMA channel select bits */
  if (devc->dma <= 3)
    temp |= 0x80;		/* 8 bit DMA channel */

  temp |= 1;			/* Trigger DMA */
  sscape_write (devc, GA_DMAA_REG, temp);
  temp &= 0xfe;			/* Clear DMA trigger */
  sscape_write (devc, GA_DMAA_REG, temp);
}
Beispiel #2
0
void
sscapeintr(int irq)
{
    u_char   bits, tmp;

    DEB(printf("sscapeintr(0x%02x)\n", (bits = sscape_read(devc, GA_INTSTAT_REG))));
    if ((sscape_sleep_flag.mode & WK_SLEEP)) {
	sscape_sleep_flag.mode = WK_WAKEUP;
	wakeup(sscape_sleeper);
    }
    if (bits & 0x02) {	/* Host interface interrupt */
	printf("SSCAPE: Host interrupt, data=%02x\n", host_read(devc));
    }
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
    if (bits & 0x01) {
	static int debug = 0;

	mpuintr(irq);
	if (debug++ > 10) {	/* Temporary debugging hack */
	    sscape_write(devc, GA_INTENA_REG, 0x00); /* Disable all interr. */
	}
    }
#endif

    /*
     * Acknowledge interrupts (toggle the interrupt bits)
     */

    tmp = sscape_read(devc, GA_INTENA_REG);
    sscape_write(devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));
}
static void sscape_pnp_start_dma(sscape_info* devc, int arg )
{
	int reg;
	if (arg == 0) reg = 2;
	else reg = 3;

	sscape_write(devc, reg, sscape_read( devc, reg) | 0x01);
	sscape_write(devc, reg, sscape_read( devc, reg) & 0xFE);
}
Beispiel #4
0
void
attach_ss_mss(struct address_info * hw_config)
{
    /*
     * This routine configures the SoundScape card for use with the Win
     * Sound System driver. The AD1848 codec interface uses the CD-ROM
     * config registers of the "ODIE".
     */

    int             i, irq_bits = 0xff;

#ifndef CONFIG_NATIVE_PCM
    int             prev_devs = num_audiodevs;
#endif

    /*
     * Setup the DMA polarity.
     */
    sscape_write(devc, GA_DMACFG_REG, 0x50);

    /*
     * Take the gate-arry off of the DMA channel.
     */
    sscape_write(devc, GA_DMAB_REG, 0x20);

    /*
     * Init the AD1848 (CD-ROM) config reg.
     */

    for (i = 0; i < sizeof(valid_interrupts); i++)
	if (hw_config->irq == valid_interrupts[i]) {
	    irq_bits = i;
	    break;
	}
    sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) |
	     (irq_bits << 1));

    if (hw_config->irq == devc->irq)
	printf("SoundScape: Warning! WSS mode can't share IRQ with MIDI\n");

    ad1848_init("SoundScape", hw_config->io_base,
		    hw_config->irq,
		    hw_config->dma,
		    hw_config->dma,
		    0,
		    devc->osp);

#ifndef CONFIG_NATIVE_PCM
    /* Check if the AD1848 driver installed itself */
    if (num_audiodevs == (prev_devs + 1))
	audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
#endif

    return;
}
Beispiel #5
0
static int __init probe_sscape(struct address_info *hw_config)
{
    devc->base = hw_config->io_base;
    devc->irq = hw_config->irq;
    devc->dma = hw_config->dma;
    devc->osp = hw_config->osp;

#ifdef SSCAPE_DEBUG1
    /*
     * Temporary debugging aid. Print contents of the registers before
     * changing them.
     */
    {
        int i;

        for (i = 0; i < 13; i++)
            printk("I%d = %02x (old value)\n", i, sscape_read(devc, i));
    }
#endif
    devc->failed = 1;

    sscape_ports = request_region(devc->base, 2, "mpu401");
    if (!sscape_ports)
        return 0;

    if (!request_region(devc->base + 2, 6, "SoundScape")) {
        release_region(devc->base, 2);
        return 0;
    }

    if (!detect_ga(devc)) {
        if (detect_sscape_pnp(devc))
            return 1;
        release_region(devc->base, 2);
        release_region(devc->base + 2, 6);
        return 0;
    }

    if (old_hardware)	/* Check that it's really an old Spea/Reveal card. */
    {
        unsigned char   tmp;
        int             cc;

        if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0))
        {
            sscape_write(devc, GA_HMCTL_REG, tmp | 0x80);
            for (cc = 0; cc < 200000; ++cc)
                inb(devc->base + ODIE_ADDR);
        }
    }
    return 1;
}
Beispiel #6
0
void
sscapeintr (int irq, void *dev_id, struct pt_regs *dummy)
{
  unsigned char   bits, tmp;
  static int      debug = 0;

  bits = sscape_read (devc, GA_INTSTAT_REG);
  if ((sscape_sleep_flag.flags & WK_SLEEP))
    {
      {
	sscape_sleep_flag.flags = WK_WAKEUP;
	module_wake_up (&sscape_sleeper);
      };
    }

  if (bits & 0x02)		/* Host interface interrupt */
    {
      printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc));
    }

#if defined(CONFIG_MPU_EMU) && defined(CONFIG_MIDI)
  if (bits & 0x01)
    {
      mpuintr (irq, NULL, NULL);
      if (debug++ > 10)		/* Temporary debugging hack */
	{
	  sscape_write (devc, GA_INTENA_REG, 0x00);	/* Disable all interrupts */
	}
    }
#endif

  /*
     * Acknowledge interrupts (toggle the interrupt bits)
   */

  tmp = sscape_read (devc, GA_INTENA_REG);
  sscape_write (devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));

}
static void sscape_coproc_close(void *dev_info, int sub_device)
{
	struct sscape_info *devc = dev_info;
	unsigned long   flags;

	save_flags(flags);
	cli();
	if (devc->dma_allocated)
	{
		sscape_write(devc, GA_DMAA_REG, 0x20);	/* DMA channel disabled */
		devc->dma_allocated = 0;
	}
	restore_flags(flags);
	return;
}
Beispiel #8
0
int probe_sscape(struct address_info *hw_config)
{

	if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
		return 0;

	devc->base = hw_config->io_base;
	devc->irq = hw_config->irq;
	devc->dma = hw_config->dma;
	devc->osp = hw_config->osp;

#ifdef SSCAPE_DEBUG1
	/*
	 * Temporary debugging aid. Print contents of the registers before
	 * changing them.
	 */
	{
		int i;

		for (i = 0; i < 13; i++)
			printk("I%d = %02x (old value)\n", i, sscape_read(devc, i));
	}
#endif
	devc->failed = 1;

	if (!detect_ga(devc))
		return 0;

	if (old_hardware)	/* Check that it's really an old Spea/Reveal card. */
	{
		unsigned char   tmp;
		int             cc;

		if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0))
		{
			sscape_write(devc, GA_HMCTL_REG, tmp | 0x80);
			for (cc = 0; cc < 200000; ++cc)
				inb(devc->base + ODIE_ADDR);
		}
	}
	sscape_detected = hw_config->io_base;
	return 1;
}
Beispiel #9
0
static void
sscape_coproc_close(void *dev_info, int sub_device)
{
    struct sscape_info *devc = dev_info;
    u_long   flags;

    flags = splhigh();
    if (devc->dma_allocated) {
	sscape_write(devc, GA_DMAA_REG, 0x20);	/* DMA channel disabled */
#ifdef CONFIG_NATIVE_PCM
#endif
	devc->dma_allocated = 0;
    }
    sscape_sleep_flag.aborting = 0;
    sscape_sleep_flag.mode = WK_NONE;
    splx(flags);

    return;
}
Beispiel #10
0
int
probe_sscape (struct address_info *hw_config)
{
  unsigned char   save;

  devc->failed = 1;
  devc->base = hw_config->io_base;
  devc->irq = hw_config->irq;
  devc->dma = hw_config->dma;
  devc->osp = hw_config->osp;

  if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
    return 0;

  /*
     * First check that the address register of "ODIE" is
     * there and that it has exactly 4 writable bits.
     * First 4 bits
   */
  if ((save = inb (PORT (ODIE_ADDR))) & 0xf0)
    return 0;

  outb (0x00, PORT (ODIE_ADDR));
  if (inb (PORT (ODIE_ADDR)) != 0x00)
    return 0;

  outb (0xff, PORT (ODIE_ADDR));
  if (inb (PORT (ODIE_ADDR)) != 0x0f)
    return 0;

  outb (save, PORT (ODIE_ADDR));

  /*
     * Now verify that some indirect registers return zero on some bits.
     * This may break the driver with some future revisions of "ODIE" but...
   */

  if (sscape_read (devc, 0) & 0x0c)
    return 0;

  if (sscape_read (devc, 1) & 0x0f)
    return 0;

  if (sscape_read (devc, 5) & 0x0f)
    return 0;

#ifdef SSCAPE_DEBUG1
  /*
     * Temporary debugging aid. Print contents of the registers before
     * changing them.
   */
  {
    int             i;

    for (i = 0; i < 13; i++)
      printk ("I%d = %02x (old value)\n", i, sscape_read (devc, i));
  }
#endif

  if (old_hardware)		/* Check that it's really an old Spea/Reveal card. */
    {
      unsigned char   tmp;
      int             cc;

      if (!((tmp = sscape_read (devc, GA_HMCTL_REG)) & 0xc0))
	{
	  sscape_write (devc, GA_HMCTL_REG, tmp | 0x80);
	  for (cc = 0; cc < 200000; ++cc)
	    inb (devc->base + ODIE_ADDR);
	}
      else
	old_hardware = 0;
    }


  sscape_detected = hw_config->io_base;

  return 1;
}
static void __init attach_ss_ms_sound(struct address_info *hw_config)
{
	/*
	 * This routine configures the SoundScape card for use with the
	 * Win Sound System driver. The AD1848 codec interface uses the CD-ROM
	 * config registers of the "ODIE".
	 */

	int i, irq_bits = 0xff;

 		
 	if (!sscape_is_pnp)  /*pnp is already setup*/
 	{
 		/*
     		 * Setup the DMA polarity.
 	    	 */
 		sscape_write(devc, GA_DMACFG_REG, 0x50);
 	
 		/*
 		 * Take the gate-array off of the DMA channel.
 		 */
 		sscape_write(devc, GA_DMAB_REG, 0x20);
 	
 		/*
 		 * Init the AD1848 (CD-ROM) config reg.
 		 */
 		for (i = 0; i < sizeof(valid_interrupts); i++)
 		{
 			if (hw_config->irq == valid_interrupts[i])
 			{
 				irq_bits = i;
 				break;
 			}
 		}	
 		sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
 	}
 	
 	if (hw_config->irq == devc->irq)
 		printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n");
 				
	hw_config->slots[0] = ad1848_init(
			sscape_is_pnp ? "SoundScape" : "SoundScape PNP",
			hw_config->io_base,
			hw_config->irq,
			hw_config->dma,
			hw_config->dma,
			0,
			devc->osp,
			THIS_MODULE);

 					  
	if (hw_config->slots[0] != -1)	/* The AD1848 driver installed itself */
	{
		audio_devs[hw_config->slots[0]]->coproc = &sscape_coproc_operations;
		devc->codec_audiodev = hw_config->slots[0];
		devc->my_audiodev = hw_config->slots[0];

		/* Set proper routings here (what are they) */
		AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
	}
		
#ifdef SSCAPE_DEBUG5
	/*
	 * Temporary debugging aid. Print contents of the registers
	 * after the AD1848 device has been initialized.
	 */
	{
		int i;

		for (i = 0; i < 13; i++)
			printk("I%d = %02x\n", i, sscape_read(devc, i));
	}
#endif

}
static int __init detect_sscape_pnp(sscape_info* devc)
{
	long	 i, irq_bits = 0xff;
	unsigned int d;

	DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base));

	if (check_region(devc->base, 8)) {
		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->base);	
		return 0;
	}
		
	if (check_region(devc->codec, 2)) {
		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec);	
		return 0;
	}

	if ( (inb( devc -> base + 2) & 0x78) != 0) return 0;

	d = inb ( devc -> base + 4) & 0xF0;
	if (  (d & 0x80) != 0)  return 0;
	
	if (d == 0) {
			devc->codec_type = 1;
			devc->ic_type = IC_ODIE;
	}
	else if ( (d & 0x60) != 0) {
			devc->codec_type = 2;
			devc->ic_type = IC_OPUS;
	}
	else if ( (d & 0x40) != 0) {
			devc->codec_type = 2;
			devc->ic_type = IC_ODIE;
	} 
	else return 0;
	
	sscape_is_pnp = 1;
		
	outb(0xFA, devc -> base+4);
	if  ((inb( devc -> base+4) & 0x9F) != 0x0A)
		return 0;
	outb(0xFE, devc -> base+4);
	if  ( (inb(devc -> base+4) & 0x9F) != 0x0E)
		return 0;
	if  ( (inb(devc -> base+5) & 0x9F) != 0x0E)
		return 0;

	if (devc->codec_type == 2) {
		if (devc -> codec != devc -> base + 8)
			printk("soundscape warning: incorrect codec port specified\n");
		devc -> codec = devc -> base + 8;
		d = 0x10 | (sscape_read(devc, 9)  & 0xCF);
		sscape_write(devc, 9, d);
		sscape_write(devc, 6, 0x80);
	} else {
		//todo: check codec is not base + 8
	}

	d  = (sscape_read(devc, 9) & 0x3F) | 0xC0;
	sscape_write(devc, 9, d);

	for (i = 0; i < 550000; i++)
		if ( !(inb(devc -> codec) & 0x80) ) break;

	d = inb(devc -> codec);
	if (d & 0x80)
		return 0;
	if ( inb(devc -> codec + 2) == 0xFF)
		return 0;

	sscape_write(devc, 9, sscape_read(devc, 9)  & 0x3F );

	d  = inb(devc -> codec) & 0x80;
	if ( d == 0) {
		printk(KERN_INFO "soundscape: hardware detected\n");
		valid_interrupts = valid_interrupts_new;
	} else	{
		printk(KERN_INFO "soundscape: board looks like media fx\n");
		valid_interrupts = valid_interrupts_old;
		old_hardware = 1;
	}

	sscape_write( devc, 9, 0xC0 | (sscape_read(devc, 9)  & 0x3F) );

	for (i = 0; i < 550000; i++)
		if ( !(inb(devc -> codec) & 0x80)) 
			break;
		
	sscape_pnp_init_hw(devc);

	for (i = 0; i < sizeof(valid_interrupts); i++)
	{
		if (devc->codec_irq == valid_interrupts[i]) {
			irq_bits = i;
			break;
		}
	}	
	sscape_write(devc, GA_INTENA_REG, 0x00);
	sscape_write(devc, GA_DMACFG_REG, 0x50);
	sscape_write(devc, GA_DMAA_REG, 0x70);
	sscape_write(devc, GA_DMAB_REG, 0x20);
	sscape_write(devc, GA_INTCFG_REG, 0xf0);
	sscape_write(devc, GA_CDCFG_REG, 0x89 | (devc->dma << 4) | (irq_bits << 1));

	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20);
	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20);

	return 1;	
}
static void __init sscape_pnp_init_hw(sscape_info* devc)
{	
	unsigned char midi_irq = 0, sb_irq = 0;
	unsigned i;
	static	char code_file_name[23] = "/sndscape/sndscape.cox";
	
	int sscape_sb_enable		= 0;
	int sscape_joystic_enable	= 0x7f;
	int sscape_mic_enable		= 0;
	int sscape_ext_midi		= 0;		

	if ( !sscape_pnp_alloc_dma(devc) ) {
		printk(KERN_ERR "sscape: faild to allocate dma\n");
		return;
	}

	for (i = 0; i < 4; i++) {
		if ( devc -> irq   == valid_interrupts[i] ) 
			midi_irq = i;
		if ( devc -> codec_irq == valid_interrupts[i] ) 
			sb_irq = i;
	}

	sscape_write( devc, 5, 0x50);
	sscape_write( devc, 7, 0x2e);
	sscape_write( devc, 8, 0x00);

	sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
	sscape_write( devc, 3, ( devc -> dma << 4) | 0x80);

	if ( sscape_sb_enable )
		sscape_write (devc, 4, 0xF0 | (sb_irq << 2) | midi_irq);
	else	
		sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq);

	i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0);
	if ( sscape_sb_enable )
		i |= devc->ic_type == IC_ODIE ? 0x05 : 0x07;	    
	if (sscape_joystic_enable) i |= 8;
	
	sscape_write (devc, 9, i);
	sscape_write (devc, 6, 0x80);
	sscape_write (devc, 1, 0x80);

	if (devc -> codec_type == 2) {
		sscape_pnp_write_codec( devc, 0x0C, 0x50);
		sscape_pnp_write_codec( devc, 0x10, sscape_pnp_read_codec( devc, 0x10) & 0x3F);
		sscape_pnp_write_codec( devc, 0x11, sscape_pnp_read_codec( devc, 0x11) | 0xC0);
		sscape_pnp_write_codec( devc, 29, 0x20);
	}

	if (sscape_pnp_upload_file(devc, "/sndscape/scope.cod") == 0 ) {
		printk(KERN_ERR "sscape: faild to upload file /sndscape/scope.cod\n");
		sscape_pnp_free_dma(devc);
		return;
	}

	i = sscape_read_host_ctrl( devc );
	
	if ( (i & 0x0F) >  7 ) {
		printk(KERN_ERR "sscape: scope.cod faild\n");
		sscape_pnp_free_dma(devc);
		return;
	}
	if ( i & 0x10 ) sscape_write( devc, 7, 0x2F);
	code_file_name[21] = (char) ( i & 0x0F) + 0x30;
	if (sscape_pnp_upload_file( devc, code_file_name) == 0) {
		printk(KERN_ERR "sscape: faild to upload file %s\n", code_file_name);
		sscape_pnp_free_dma(devc);
		return;
	}
	
	if (devc->ic_type != IC_ODIE) {
		sscape_pnp_write_codec( devc, 10, (sscape_pnp_read_codec(devc, 10) & 0x7f) |
		 ( sscape_mic_enable == 0 ? 0x00 : 0x80) );
	}
	sscape_write_host_ctrl2( devc, 0x84, 0x64 );  /* MIDI volume */
	sscape_write_host_ctrl2( devc, 0x86, 0x64 );  /* MIDI volume?? */
	sscape_write_host_ctrl2( devc, 0x8A, sscape_ext_midi);

	sscape_pnp_write_codec ( devc, 6, 0x3f ); //WAV_VOL
	sscape_pnp_write_codec ( devc, 7, 0x3f ); //WAV_VOL
	sscape_pnp_write_codec ( devc, 2, 0x1F ); //WD_CDXVOLL
	sscape_pnp_write_codec ( devc, 3, 0x1F ); //WD_CDXVOLR

	if (devc -> codec_type == 1) {
		sscape_pnp_write_codec ( devc, 4, 0x1F );
		sscape_pnp_write_codec ( devc, 5, 0x1F );
		sscape_write_host_ctrl2( devc, 0x88, sscape_mic_enable);
	} else {
		int t;
		sscape_pnp_write_codec ( devc, 0x10, 0x1F << 1);
		sscape_pnp_write_codec ( devc, 0x11, 0xC0 | (0x1F << 1));

		t = sscape_pnp_read_codec( devc, 0x00) & 0xDF;
		if ( (sscape_mic_enable == 0)) t |= 0;
		else t |= 0x20;
		sscape_pnp_write_codec ( devc, 0x00, t);
		t = sscape_pnp_read_codec( devc, 0x01) & 0xDF;
		if ( (sscape_mic_enable == 0) ) t |= 0;
		else t |= 0x20;
		sscape_pnp_write_codec ( devc, 0x01, t);
		sscape_pnp_write_codec ( devc, 0x40 | 29 , 0x20);
		outb(0, devc -> codec);
	}
	if (devc -> ic_type == IC_OPUS ) {
		int i = sscape_read( devc, 9 );
		sscape_write( devc, 9, i | 3 );
		sscape_write( devc, 3, 0x40);

		if (check_region(0x228, 1)) {
		    	    outb(0, 0x228);
			    release_region(0x228,1);
		}
		sscape_write( devc, 3, (devc -> dma << 4) | 0x80);
		sscape_write( devc, 9, i );
	}
	
	host_close ( devc );
	sscape_pnp_free_dma(devc);
}
Beispiel #14
0
static int __init init_ss_ms_sound(struct address_info *hw_config)
{
    int i, irq_bits = 0xff;
    int ad_flags = 0;
    struct resource *ports;

    if (devc->failed)
    {
        printk(KERN_ERR "soundscape: Card not detected\n");
        return 0;
    }
    if (devc->ok == 0)
    {
        printk(KERN_ERR "soundscape: Invalid initialization order.\n");
        return 0;
    }
    for (i = 0; i < 4; i++)
    {
        if (hw_config->irq == valid_interrupts[i])
        {
            irq_bits = i;
            break;
        }
    }
    if (irq_bits == 0xff) {
        printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq);
        return 0;
    }

    if (old_hardware)
        ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
    else if (sscape_is_pnp)
        ad_flags = 0x87654321;  /* Tell that we have a soundscape pnp with 1845 chip */

    ports = request_region(hw_config->io_base, 4, "ad1848");
    if (!ports) {
        printk(KERN_ERR "soundscape: ports busy\n");
        return 0;
    }

    if (!ad1848_detect(ports, &ad_flags, hw_config->osp)) {
        release_region(hw_config->io_base, 4);
        return 0;
    }

    if (!sscape_is_pnp)  /*pnp is already setup*/
    {
        /*
        	 * Setup the DMA polarity.
        	 */
        sscape_write(devc, GA_DMACFG_REG, 0x50);

        /*
         * Take the gate-array off of the DMA channel.
         */
        sscape_write(devc, GA_DMAB_REG, 0x20);

        /*
         * Init the AD1848 (CD-ROM) config reg.
         */
        sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
    }

    if (hw_config->irq == devc->irq)
        printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n");

    hw_config->slots[0] = ad1848_init(
                              sscape_is_pnp ? "SoundScape" : "SoundScape PNP",
                              ports,
                              hw_config->irq,
                              hw_config->dma,
                              hw_config->dma,
                              0,
                              devc->osp,
                              THIS_MODULE);


    if (hw_config->slots[0] != -1)	/* The AD1848 driver installed itself */
    {
        audio_devs[hw_config->slots[0]]->coproc = &sscape_coproc_operations;
        devc->codec_audiodev = hw_config->slots[0];
        devc->my_audiodev = hw_config->slots[0];

        /* Set proper routings here (what are they) */
        AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
    }

#ifdef SSCAPE_DEBUG5
    /*
     * Temporary debugging aid. Print contents of the registers
     * after the AD1848 device has been initialized.
     */
    {
        int i;

        for (i = 0; i < 13; i++)
            printk("I%d = %02x\n", i, sscape_read(devc, i));
    }
#endif
    return 1;
}
Beispiel #15
0
/*
 * Upload a byte-stream into the SoundScape using DMA channel A.
 */
static int upload_dma_data(struct soundscape *s,
                           const unsigned char __user *data,
                           size_t size)
{
	unsigned long flags;
	struct snd_dma_buffer dma;
	int ret;

	if (!get_dmabuf(&dma, PAGE_ALIGN(size)))
		return -ENOMEM;

	spin_lock_irqsave(&s->lock, flags);

	/*
	 * Reset the board ...
	 */
	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f);

	/*
	 * Enable the DMA channels and configure them ...
	 */
	sscape_write_unsafe(s->io_base, GA_DMACFG_REG, 0x50);
	sscape_write_unsafe(s->io_base, GA_DMAA_REG, (s->chip->dma1 << 4) | DMA_8BIT);
	sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20);

	/*
	 * Take the board out of reset ...
	 */
	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x80);

	/*
	 * Upload the user's data (firmware?) to the SoundScape
	 * board through the DMA channel ...
	 */
	while (size != 0) {
		unsigned long len;

		/*
		 * Apparently, copying to/from userspace can sleep.
		 * We are therefore forbidden from holding any
		 * spinlocks while we copy ...
		 */
		spin_unlock_irqrestore(&s->lock, flags);

		/*
		 * Remember that the data that we want to DMA
		 * comes from USERSPACE. We have already verified
		 * the userspace pointer ...
		 */
		len = min(size, dma.bytes);
		len -= __copy_from_user(dma.area, data, len);
		data += len;
		size -= len;

		/*
		 * Grab that spinlock again, now that we've
		 * finished copying!
		 */
		spin_lock_irqsave(&s->lock, flags);

		snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE);
		sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG);
		if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) {
			/*
			 * Don't forget to release this spinlock we're holding ...
			 */
			spin_unlock_irqrestore(&s->lock, flags);

			snd_printk(KERN_ERR "sscape: DMA upload has timed out\n");
			ret = -EAGAIN;
			goto _release_dma;
		}
	} /* while */

	set_host_mode_unsafe(s->io_base);

	/*
	 * Boot the board ... (I think)
	 */
	sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x40);
	spin_unlock_irqrestore(&s->lock, flags);

	/*
	 * If all has gone well, then the board should acknowledge
	 * the new upload and tell us that it has rebooted OK. We
	 * give it 5 seconds (max) ...
	 */
	ret = 0;
	if (!obp_startup_ack(s, 5)) {
		snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n");
		ret = -EAGAIN;
	} else if (!host_startup_ack(s, 5)) {
		snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n");
		ret = -EAGAIN;
	}

	_release_dma:
	/*
	 * NOTE!!! We are NOT holding any spinlocks at this point !!!
	 */
	sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_ODIE ? 0x70 : 0x40));
	free_dmabuf(&dma);

	return ret;
}
Beispiel #16
0
static int
sscape_download_boot(struct sscape_info * devc, u_char *block, int size, int flag)
{
    u_long   flags;
    u_char   temp;
    int             done, timeout_val;

    if (flag & CPF_FIRST) {
	/*
	 * First block. Have to allocate DMA and to reset the board
	 * before continuing.
	 */

	flags = splhigh();
	if (devc->dma_allocated == 0) {
	    devc->dma_allocated = 1;
	}
	splx(flags);

	sscape_write(devc, GA_HMCTL_REG,
	   (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f);	/* Reset */

	for (timeout_val = 10000; timeout_val > 0; timeout_val--)
	    sscape_read(devc, GA_HMCTL_REG);	/* Delay */

	/* Take board out of reset */
	sscape_write(devc, GA_HMCTL_REG,
		   (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80);
    }
    /*
     * Transfer one code block using DMA
     */
    bcopy(block, audio_devs[devc->my_audiodev]->dmap_out->raw_buf, size);

    flags = splhigh();
    /******** INTERRUPTS DISABLED NOW ********/
    do_dma(devc, SSCAPE_DMA_A,
	       audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys,
	       size, 1);

    /*
     * Wait until transfer completes.
     */
    sscape_sleep_flag.aborting = 0;
    sscape_sleep_flag.mode = WK_NONE;
    done = 0;
    timeout_val = 100;
    while (!done && timeout_val-- > 0) {
	int   chn;
	sscape_sleeper = &chn;
	DO_SLEEP(chn, sscape_sleep_flag, 1);

	done = 1;
    }

    splx(flags);
    if (!done)
	return 0;

    if (flag & CPF_LAST) {
	/*
	 * Take the board out of reset
	 */
	outb(PORT(HOST_CTRL), 0x00);
	outb(PORT(MIDI_CTRL), 0x00);

	temp = sscape_read(devc, GA_HMCTL_REG);
	temp |= 0x40;
	sscape_write(devc, GA_HMCTL_REG, temp);	/* Kickstart the board */

	/*
	 * Wait until the ODB wakes up
	 */

	flags = splhigh();
	done = 0;
	timeout_val = 5 * hz;
	while (!done && timeout_val-- > 0) {
	  int   chn;

	  sscape_sleeper = &chn;
	  DO_SLEEP(chn, sscape_sleep_flag, 1);

	  if (inb(PORT(HOST_DATA)) == 0xff)	/* OBP startup acknowledge */
	    done = 1;
	}
	splx(flags);
	if (!done) {
	    printf("SoundScape: The OBP didn't respond after code download\n");
	    return 0;
	}
	flags = splhigh();
	done = 0;
	timeout_val = 5 * hz;
	while (!done && timeout_val-- > 0) {
	  int   chn;

	  sscape_sleeper = &chn;
	  DO_SLEEP(chn, sscape_sleep_flag, 1);

	  if (inb(PORT(HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
	    done = 1;
	}
	splx(flags);
	if (!done) {
	    printf("SoundScape: OBP Initialization failed.\n");
	    return 0;
	}
	printf("SoundScape board of type %d initialized OK\n",
	       get_board_type(devc));

	set_control(devc, CTL_MASTER_VOL, 100);
	set_control(devc, CTL_SYNTH_VOL, 100);

#ifdef SSCAPE_DEBUG3
	/*
	 * Temporary debugging aid. Print contents of the registers
	 * after downloading the code.
	 */
	{
	    int             i;

	    for (i = 0; i < 13; i++)
		printf("I%d = %02x (new value)\n", i, sscape_read(devc, i));
	}
#endif

    }
    return 1;
}
Beispiel #17
0
void
attach_sscape(struct address_info * hw_config)
{
#ifndef SSCAPE_REGS
    /*
     * Config register values for Spea/V7 Media FX and Ensoniq S-2000.
     * These values are card dependent. If you have another SoundScape
     * based card, you have to find the correct values. Do the following:
     * - Compile this driver with SSCAPE_DEBUG1 defined. - Shut down and
     * power off your machine. - Boot with DOS so that the SSINIT.EXE
     * program is run. - Warm boot to {Linux|SYSV|BSD} and write down the
     * lines displayed when detecting the SoundScape. - Modify the
     * following list to use the values printed during boot. Undefine the
     * SSCAPE_DEBUG1
     */
#define SSCAPE_REGS { \
/* I0 */	0x00, \
		0xf0, /* Note! Ignored. Set always to 0xf0 */ \
		0x20, /* Note! Ignored. Set always to 0x20 */ \
		0x20, /* Note! Ignored. Set always to 0x20 */ \
		0xf5, /* Ignored */ \
		0x10, \
		0x00, \
		0x2e, /* I7 MEM config A. Likely to vary between models */ \
		0x00, /* I8 MEM config B. Likely to vary between models */ \
/* I9 */	0x40 /* Ignored */ \
	}
#endif

    u_long   flags;
    static u_char regs[10] = SSCAPE_REGS;

    int             i, irq_bits = 0xff;

    if (sscape_detected != hw_config->io_base)
	return;

    if (old_hardware) {
	valid_interrupts = valid_interrupts_old;
	conf_printf("Ensoniq Soundscape (old)", hw_config);
    } else
	conf_printf("Ensoniq Soundscape", hw_config);

    for (i = 0; i < sizeof(valid_interrupts); i++)
	if (hw_config->irq == valid_interrupts[i]) {
	    irq_bits = i;
	    break;
	}
    if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff)) {
	printf("Invalid IRQ%d\n", hw_config->irq);
	return;
    }
    flags = splhigh();

    for (i = 1; i < 10; i++)
	switch (i) {
	case 1:	/* Host interrupt enable */
	    sscape_write(devc, i, 0xf0);	/* All interrupts enabled */
	    break;

	case 2:	/* DMA A status/trigger register */
	case 3:	/* DMA B status/trigger register */
	    sscape_write(devc, i, 0x20);	/* DMA channel disabled */
	    break;

	case 4:	/* Host interrupt config reg */
	    sscape_write(devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
	    break;

	case 5:	/* Don't destroy CD-ROM DMA config bits (0xc0) */
	    sscape_write(devc, i, (regs[i] & 0x3f) |
			 (sscape_read(devc, i) & 0xc0));
	    break;

	case 6:	/* CD-ROM config. Don't touch. */
	    break;

	case 9:	/* Master control reg. Don't modify CR-ROM
		 * bits. Disable SB emul */
	    sscape_write(devc, i, (sscape_read(devc, i) & 0xf0) | 0x00);
	    break;

	default:
	    sscape_write(devc, i, regs[i]);
	}

    splx(flags);

#ifdef SSCAPE_DEBUG2
    /*
     * Temporary debugging aid. Print contents of the registers after
     * changing them.
     */
    {
	int             i;

	for (i = 0; i < 13; i++)
	    printf("I%d = %02x (new value)\n", i, sscape_read(devc, i));
    }
#endif

#if defined(CONFIG_MIDI) && defined(CONFIG_MPU_EMU)
    if (probe_mpu401(hw_config))
	hw_config->always_detect = 1;
    {
	int             prev_devs;

	prev_devs = num_midis;
	attach_mpu401(hw_config);

	if (num_midis == (prev_devs + 1))	/* The MPU driver
						 * installed itself */
	    midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
    }
#endif

#ifndef EXCLUDE_NATIVE_PCM
    /* Not supported yet */

#ifdef CONFIG_AUDIO
    if (num_audiodevs < MAX_AUDIO_DEV) {
	int my_dev;

	audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;
	audio_devs[my_dev]->dmachan1 = hw_config->dma;
	audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
	audio_devs[my_dev]->devc = devc;
	devc->my_audiodev = my_dev;
	devc->opened = 0;
	audio_devs[my_dev]->coproc = &sscape_coproc_operations;
	if (snd_set_irq_handler(hw_config->irq, sscapeintr, devc->osp) < 0)
	    printf("Error: Can't allocate IRQ for SoundScape\n");
	sscape_write(devc, GA_INTENA_REG, 0x80);	/* Master IRQ enable */
    } else
	printf("SoundScape: More than enough audio devices detected\n");
#endif
#endif
    devc->ok = 1;
    devc->failed = 0;
    return;
}
static int sscape_download_boot(struct sscape_info *devc, unsigned char *block, int size, int flag)
{
	unsigned long flags;
	unsigned char temp;
	volatile int done, timeout_val;
	static unsigned char codec_dma_bits = 0;

	if (flag & CPF_FIRST)
	{
		/*
		 * First block. Have to allocate DMA and to reset the board
		 * before continuing.
		 */

		save_flags(flags);
		cli();
		codec_dma_bits = sscape_read(devc, GA_CDCFG_REG);

		if (devc->dma_allocated == 0)
			devc->dma_allocated = 1;

		restore_flags(flags);

		sscape_write(devc, GA_HMCTL_REG, 
			(temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f);	/*Reset */

		for (timeout_val = 10000; timeout_val > 0; timeout_val--)
			sscape_read(devc, GA_HMCTL_REG);	/* Delay */

		/* Take board out of reset */
		sscape_write(devc, GA_HMCTL_REG,
			(temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80);
	}
	/*
	 * Transfer one code block using DMA
	 */
	if (audio_devs[devc->codec_audiodev]->dmap_out->raw_buf == NULL)
	{
		printk(KERN_WARNING "soundscape: DMA buffer not available\n");
		return 0;
	}
	memcpy(audio_devs[devc->codec_audiodev]->dmap_out->raw_buf, block, size);

	save_flags(flags);
	cli();
	
	/******** INTERRUPTS DISABLED NOW ********/
	
	do_dma(devc, SSCAPE_DMA_A,
	       audio_devs[devc->codec_audiodev]->dmap_out->raw_buf_phys,
	       size, DMA_MODE_WRITE);

	/*
	 * Wait until transfer completes.
	 */
	
	done = 0;
	timeout_val = 30;
	while (!done && timeout_val-- > 0)
	{
		int resid;

		if (HZ / 50)
			sleep(HZ / 50);
		clear_dma_ff(devc->dma);
		if ((resid = get_dma_residue(devc->dma)) == 0)
			done = 1;
	}

	restore_flags(flags);
	if (!done)
		return 0;

	if (flag & CPF_LAST)
	{
		/*
		 * Take the board out of reset
		 */
		outb((0x00), PORT(HOST_CTRL));
		outb((0x00), PORT(MIDI_CTRL));

		temp = sscape_read(devc, GA_HMCTL_REG);
		temp |= 0x40;
		sscape_write(devc, GA_HMCTL_REG, temp);	/* Kickstart the board */

		/*
		 * Wait until the ODB wakes up
		 */

		save_flags(flags);
		cli();
		done = 0;
		timeout_val = 5 * HZ;
		while (!done && timeout_val-- > 0)
		{
			unsigned char x;
			
			sleep(1);
			x = inb(PORT(HOST_DATA));
			if (x == 0xff || x == 0xfe)		/* OBP startup acknowledge */
			{
				DDB(printk("Soundscape: Acknowledge = %x\n", x));
				done = 1;
			}
		}
		sscape_write(devc, GA_CDCFG_REG, codec_dma_bits);

		restore_flags(flags);
		if (!done)
		{
			printk(KERN_ERR "soundscape: The OBP didn't respond after code download\n");
			return 0;
		}
		save_flags(flags);
		cli();
		done = 0;
		timeout_val = 5 * HZ;
		while (!done && timeout_val-- > 0)
		{
			sleep(1);
			if (inb(PORT(HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
				done = 1;
		}
		restore_flags(flags);
		if (!done)
		{
			printk(KERN_ERR "soundscape: OBP Initialization failed.\n");
			return 0;
		}
		printk(KERN_INFO "SoundScape board initialized OK\n");
		set_control(devc, CTL_MASTER_VOL, 100);
		set_control(devc, CTL_SYNTH_VOL, 100);

#ifdef SSCAPE_DEBUG3
		/*
		 * Temporary debugging aid. Print contents of the registers after
		 * downloading the code.
		 */
		{
			int i;

			for (i = 0; i < 13; i++)
				printk("I%d = %02x (new value)\n", i, sscape_read(devc, i));
		}
#endif

	}
	return 1;
}
Beispiel #19
0
static int
sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, int flag)
{
  unsigned long   flags;
  unsigned char   temp;
  int             done, timeout_val;
  static unsigned char codec_dma_bits = 0;

  if (flag & CPF_FIRST)
    {
      /*
         * First block. Have to allocate DMA and to reset the board
         * before continuing.
       */

      save_flags (flags);
      cli ();
      codec_dma_bits = sscape_read (devc, GA_CDCFG_REG);
#if 0
      sscape_write (devc, GA_CDCFG_REG,
		    codec_dma_bits & ~0x08);	/* Disable codec DMA */
#endif

      if (devc->dma_allocated == 0)
	{
	  devc->dma_allocated = 1;
	}
      restore_flags (flags);

      sscape_write (devc, GA_HMCTL_REG,
		    (temp = sscape_read (devc, GA_HMCTL_REG)) & 0x3f);	/*Reset */

      for (timeout_val = 10000; timeout_val > 0; timeout_val--)
	sscape_read (devc, GA_HMCTL_REG);	/* Delay */

      /* Take board out of reset */
      sscape_write (devc, GA_HMCTL_REG,
		    (temp = sscape_read (devc, GA_HMCTL_REG)) | 0x80);
    }

  /*
   * Transfer one code block using DMA
   */
  memcpy (audio_devs[devc->my_audiodev]->dmap_out->raw_buf, block, size);

  save_flags (flags);
  cli ();
/******** INTERRUPTS DISABLED NOW ********/
  do_dma (devc, SSCAPE_DMA_A,
	  audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys,
	  size, DMA_MODE_WRITE);

  /*
   * Wait until transfer completes.
   */
  sscape_sleep_flag.flags = WK_NONE;
  done = 0;
  timeout_val = 100;
  while (!done && timeout_val-- > 0)
    {
      int             resid;


      {
	unsigned long   tlimit;

	if (1)
	  current_set_timeout (tlimit = jiffies + (1));
	else
	  tlimit = (unsigned long) -1;
	sscape_sleep_flag.flags = WK_SLEEP;
	module_interruptible_sleep_on (&sscape_sleeper);
	if (!(sscape_sleep_flag.flags & WK_WAKEUP))
	  {
	    if (jiffies >= tlimit)
	      sscape_sleep_flag.flags |= WK_TIMEOUT;
	  }
	sscape_sleep_flag.flags &= ~WK_SLEEP;
      };
      clear_dma_ff (devc->dma);
      if ((resid = get_dma_residue (devc->dma)) == 0)
	{
	  done = 1;
	}
    }

  restore_flags (flags);
  if (!done)
    return 0;

  if (flag & CPF_LAST)
    {
      /*
         * Take the board out of reset
       */
      outb (0x00, PORT (HOST_CTRL));
      outb (0x00, PORT (MIDI_CTRL));

      temp = sscape_read (devc, GA_HMCTL_REG);
      temp |= 0x40;
      sscape_write (devc, GA_HMCTL_REG, temp);	/* Kickstart the board */

      /*
         * Wait until the ODB wakes up
       */

      save_flags (flags);
      cli ();
      done = 0;
      timeout_val = 5 * HZ;
      while (!done && timeout_val-- > 0)
	{

	  {
	    unsigned long   tlimit;

	    if (1)
	      current_set_timeout (tlimit = jiffies + (1));
	    else
	      tlimit = (unsigned long) -1;
	    sscape_sleep_flag.flags = WK_SLEEP;
	    module_interruptible_sleep_on (&sscape_sleeper);
	    if (!(sscape_sleep_flag.flags & WK_WAKEUP))
	      {
		if (jiffies >= tlimit)
		  sscape_sleep_flag.flags |= WK_TIMEOUT;
	      }
	    sscape_sleep_flag.flags &= ~WK_SLEEP;
	  };
	  if (inb (PORT (HOST_DATA)) == 0xff)	/* OBP startup acknowledge */
	    done = 1;
	}
      sscape_write (devc, GA_CDCFG_REG, codec_dma_bits);

      restore_flags (flags);
      if (!done)
	{
	  printk ("SoundScape: The OBP didn't respond after code download\n");
	  return 0;
	}

      save_flags (flags);
      cli ();
      done = 0;
      timeout_val = 5 * HZ;
      while (!done && timeout_val-- > 0)
	{

	  {
	    unsigned long   tlimit;

	    if (1)
	      current_set_timeout (tlimit = jiffies + (1));
	    else
	      tlimit = (unsigned long) -1;
	    sscape_sleep_flag.flags = WK_SLEEP;
	    module_interruptible_sleep_on (&sscape_sleeper);
	    if (!(sscape_sleep_flag.flags & WK_WAKEUP))
	      {
		if (jiffies >= tlimit)
		  sscape_sleep_flag.flags |= WK_TIMEOUT;
	      }
	    sscape_sleep_flag.flags &= ~WK_SLEEP;
	  };
	  if (inb (PORT (HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
	    done = 1;
	}
      restore_flags (flags);
      if (!done)
	{
	  printk ("SoundScape: OBP Initialization failed.\n");
	  return 0;
	}

      printk ("SoundScape board of type %d initialized OK\n",
	      get_board_type (devc));

      set_control (devc, CTL_MASTER_VOL, 100);
      set_control (devc, CTL_SYNTH_VOL, 100);

#ifdef SSCAPE_DEBUG3
      /*
         * Temporary debugging aid. Print contents of the registers after
         * downloading the code.
       */
      {
	int             i;

	for (i = 0; i < 13; i++)
	  printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i));
      }
#endif

    }

  return 1;
}
void __init attach_sscape(struct address_info *hw_config)
{
#ifndef SSCAPE_REGS
	/*
	 * Config register values for Spea/V7 Media FX and Ensoniq S-2000.
	 * These values are card
	 * dependent. If you have another SoundScape based card, you have to
	 * find the correct values. Do the following:
	 *  - Compile this driver with SSCAPE_DEBUG1 defined.
	 *  - Shut down and power off your machine.
	 *  - Boot with DOS so that the SSINIT.EXE program is run.
	 *  - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed
	 *    when detecting the SoundScape.
	 *  - Modify the following list to use the values printed during boot.
	 *    Undefine the SSCAPE_DEBUG1
	 */
#define SSCAPE_REGS { \
/* I0 */	0x00, \
/* I1 */	0xf0, /* Note! Ignored. Set always to 0xf0 */ \
/* I2 */	0x20, /* Note! Ignored. Set always to 0x20 */ \
/* I3 */	0x20, /* Note! Ignored. Set always to 0x20 */ \
/* I4 */	0xf5, /* Ignored */ \
/* I5 */	0x10, \
/* I6 */	0x00, \
/* I7 */	0x2e, /* I7 MEM config A. Likely to vary between models */ \
/* I8 */	0x00, /* I8 MEM config B. Likely to vary between models */ \
/* I9 */	0x40 /* Ignored */ \
	}
#endif

	unsigned long   flags;
	static unsigned char regs[10] = SSCAPE_REGS;

	int i, irq_bits = 0xff;

	if (sscape_detected != hw_config->io_base)
		return;

	request_region(devc->base + 2, 6, "SoundScape");
	if (old_hardware)
	{
		valid_interrupts = valid_interrupts_old;
		conf_printf("Ensoniq SoundScape (old)", hw_config);
	}
	else
		conf_printf("Ensoniq SoundScape", hw_config);

	for (i = 0; i < sizeof(valid_interrupts); i++)
	{
		if (hw_config->irq == valid_interrupts[i])
		{
			irq_bits = i;
			break;
		}
	}
	if (hw_config->irq > 15 || ((regs[4] = irq_bits) == 0xff))
	{
		printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq);
		return;
	}
	
	if (!sscape_is_pnp) {
	
	    save_flags(flags);
	    cli();
	    for (i = 1; i < 10; i++)
	    {
		switch (i)
		{
			case 1:	/* Host interrupt enable */
				sscape_write(devc, i, 0xf0);	/* All interrupts enabled */
				break;

			case 2:	/* DMA A status/trigger register */
			case 3:	/* DMA B status/trigger register */
				sscape_write(devc, i, 0x20);	/* DMA channel disabled */
				break;

			case 4:	/* Host interrupt config reg */
				sscape_write(devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
				break;

			case 5:	/* Don't destroy CD-ROM DMA config bits (0xc0) */
				sscape_write(devc, i, (regs[i] & 0x3f) | (sscape_read(devc, i) & 0xc0));
				break;

			case 6:	/* CD-ROM config (WSS codec actually) */
				sscape_write(devc, i, regs[i]);
				break;

			case 9:	/* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
				sscape_write(devc, i, (sscape_read(devc, i) & 0xf0) | 0x08);
				break;

			default:
				sscape_write(devc, i, regs[i]);
		}
	    }
	    restore_flags(flags);
	}
#ifdef SSCAPE_DEBUG2
	/*
	 * Temporary debugging aid. Print contents of the registers after
	 * changing them.
	 */
	{
		int i;

		for (i = 0; i < 13; i++)
			printk("I%d = %02x (new value)\n", i, sscape_read(devc, i));
	}
#endif

	if (probe_mpu401(hw_config))
		hw_config->always_detect = 1;
	hw_config->name = "SoundScape";

	hw_config->irq *= -1;	/* Negative value signals IRQ sharing */
	attach_mpu401(hw_config, THIS_MODULE);
	hw_config->irq *= -1;	/* Restore it */

	if (hw_config->slots[1] != -1)	/* The MPU driver installed itself */
	{
		sscape_mididev = hw_config->slots[1];
		midi_devs[hw_config->slots[1]]->coproc = &sscape_coproc_operations;
	}
	sscape_write(devc, GA_INTENA_REG, 0x80);	/* Master IRQ enable */
	devc->ok = 1;
	devc->failed = 0;
}
Beispiel #21
0
void
attach_ss_ms_sound (struct address_info *hw_config)
{
  /*
     * This routine configures the SoundScape card for use with the
     * Win Sound System driver. The AD1848 codec interface uses the CD-ROM
     * config registers of the "ODIE".
   */

  int             i, irq_bits = 0xff;

  int             prev_devs = num_audiodevs;

  hw_config->dma = devc->dma;	/* Share the DMA with the ODIE/OPUS chip */

  /*
   * Setup the DMA polarity.
   */
  sscape_write (devc, GA_DMACFG_REG, 0x50);

  /*
     * Take the gate-array off of the DMA channel.
   */
  sscape_write (devc, GA_DMAB_REG, 0x20);

  /*
     * Init the AD1848 (CD-ROM) config reg.
   */

  for (i = 0; i < sizeof (valid_interrupts); i++)
    if (hw_config->irq == valid_interrupts[i])
      {
	irq_bits = i;
	break;
      }

  sscape_write (devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) |
		(irq_bits << 1));

  if (hw_config->irq == devc->irq)
    printk ("SoundScape: Warning! The WSS mode can't share IRQ with MIDI\n");

  ad1848_init ("SoundScape", hw_config->io_base,
	       hw_config->irq,
	       hw_config->dma,
	       hw_config->dma,
	       0,
	       devc->osp);

  if (num_audiodevs == (prev_devs + 1))		/* The AD1848 driver installed itself */
    audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
  devc->my_audiodev = prev_devs;

#ifdef SSCAPE_DEBUG5
  /*
     * Temporary debugging aid. Print contents of the registers
     * after the AD1848 device has been initialized.
   */
  {
    int             i;

    for (i = 0; i < 13; i++)
      printk ("I%d = %02x\n", i, sscape_read (devc, i));
  }
#endif

}
static	int	sscape_pnp_upload_file(sscape_info* devc, char* fn)
{	
	int	     	done = 0;
	int	     	timeout_val;
	char*	     	data,*dt;
	int	     	len,l;
	unsigned long	flags;

	sscape_write( devc, 9, sscape_read(devc, 9 )  & 0x3F );
	sscape_write( devc, 2, (devc -> dma << 4) | 0x80 );
	sscape_write( devc, 3, 0x20 );
	sscape_write( devc, 9, sscape_read( devc, 9 )  | 0x80 );
	
	len = mod_firmware_load(fn, &data);
	if (len == 0) {
		    printk(KERN_ERR "sscape: file not found: %s\n", fn);
		    return 0;
	}
	dt = data;
	save_flags(flags);
	cli();
	while ( len > 0 ) {
		if (len > devc -> buffsize) l = devc->buffsize;
		else l = len;
		len -= l;		
		memcpy(devc->raw_buf, dt, l); dt += l;
		sscape_start_dma(devc->dma, devc->raw_buf_phys, l, 0x48);
		sscape_pnp_start_dma ( devc, 0 );
		if (sscape_pnp_wait_dma ( devc, 0 ) == 0) {
			restore_flags(flags);	    
			return 0;
		}
	}
	
	restore_flags(flags);	    
	vfree(data);
	
	outb(0, devc -> base + 2);
	outb(0, devc -> base);

	sscape_write ( devc, 9, sscape_read( devc, 9 ) | 0x40);

	timeout_val = 5 * HZ; 
	while (!done && timeout_val-- > 0)
	{
		unsigned char x;
		sleep(1);
		x = inb( devc -> base + 3);
		if (x == 0xff || x == 0xfe)		/* OBP startup acknowledge */
		{
			//printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
			done = 1;
		}
	}
	timeout_val = 5 * HZ;
	done = 0;
	while (!done && timeout_val-- > 0)
	{
		unsigned char x;
		sleep(1);
		x = inb( devc -> base + 3);
		if (x == 0xfe)		/* OBP startup acknowledge */
		{
			//printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
			done = 1;
		}
	}

	if ( !done ) printk(KERN_ERR "soundscape: OBP Initialization failed.\n");

	sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
	sscape_write( devc, 3, (devc -> dma << 4) + 0x80);
	return 1;
}
Beispiel #23
0
/*
 * Create an ALSA soundcard entry for the SoundScape, using
 * the given list of port, IRQ and DMA resources.
 */
static int __devinit create_sscape(int dev, struct snd_card **rcardp)
{
	struct snd_card *card;
	register struct soundscape *sscape;
	register unsigned dma_cfg;
	unsigned irq_cfg;
	unsigned mpu_irq_cfg;
	unsigned xport;
	struct resource *io_res;
	unsigned long flags;
	int err;

	/*
	 * Check that the user didn't pass us garbage data ...
	 */
	irq_cfg = get_irq_config(irq[dev]);
	if (irq_cfg == INVALID_IRQ) {
		snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
		return -ENXIO;
	}

	mpu_irq_cfg = get_irq_config(mpu_irq[dev]);
	if (mpu_irq_cfg == INVALID_IRQ) {
		printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
		return -ENXIO;
	}
	xport = port[dev];

	/*
	 * Grab IO ports that we will need to probe so that we
	 * can detect and control this hardware ...
	 */
	if ((io_res = request_region(xport, 8, "SoundScape")) == NULL) {
		snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport);
		return -EBUSY;
	}

	/*
	 * Grab both DMA channels (OK, only one for now) ...
	 */
	if ((err = request_dma(dma[dev], "SoundScape")) < 0) {
		snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]);
		goto _release_region;
	}

	/*
	 * Create a new ALSA sound card entry, in anticipation
	 * of detecting our hardware ...
	 */
	if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
				 sizeof(struct soundscape))) == NULL) {
		err = -ENOMEM;
		goto _release_dma;
	}

	sscape = get_card_soundscape(card);
	spin_lock_init(&sscape->lock);
	spin_lock_init(&sscape->fwlock);
	sscape->io_res = io_res;
	sscape->io_base = xport;

	if (!detect_sscape(sscape)) {
		printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base);
		err = -ENODEV;
		goto _release_card;
	}

	printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n",
	                 sscape->io_base, irq[dev], dma[dev]);

	/*
	 * Now create the hardware-specific device so that we can
	 * load the microcode into the on-board processor.
	 * We cannot use the MPU-401 MIDI system until this firmware
	 * has been loaded into the card.
	 */
	if ((err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw))) < 0) {
		printk(KERN_ERR "sscape: Failed to create firmware device\n");
		goto _release_card;
	}
	strlcpy(sscape->hw->name, "SoundScape M68K", sizeof(sscape->hw->name));
	sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0';
	sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE;
	sscape->hw->ops.open = sscape_hw_open;
	sscape->hw->ops.release = sscape_hw_release;
	sscape->hw->ops.ioctl = sscape_hw_ioctl;
	sscape->hw->private_data = sscape;

	/*
	 * Tell the on-board devices where their resources are (I think -
	 * I can't be sure without a datasheet ... So many magic values!)
	 */
	spin_lock_irqsave(&sscape->lock, flags);

	activate_ad1845_unsafe(sscape->io_base);

	sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x00); /* disable */
	sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e);
	sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00);

	/*
	 * Enable and configure the DMA channels ...
	 */
	sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50);
	dma_cfg = (sscape->ic_type == IC_ODIE ? 0x70 : 0x40);
	sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg);
	sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20);

	sscape_write_unsafe(sscape->io_base,
	                    GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg);
	sscape_write_unsafe(sscape->io_base,
	                    GA_CDCFG_REG, 0x09 | DMA_8BIT | (dma[dev] << 4) | (irq_cfg << 1));

	spin_unlock_irqrestore(&sscape->lock, flags);

	/*
	 * We have now enabled the codec chip, and so we should
	 * detect the AD1845 device ...
	 */
	if ((err = create_ad1845(card, CODEC_IO(xport), irq[dev], dma[dev])) < 0) {
		printk(KERN_ERR "sscape: No AD1845 device at 0x%x, IRQ %d\n",
		                CODEC_IO(xport), irq[dev]);
		goto _release_card;
	}
#define MIDI_DEVNUM  0
	if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(xport), mpu_irq[dev])) < 0) {
		printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n",
		                MPU401_IO(xport));
		goto _release_card;
	}

	/*
	 * Enable the master IRQ ...
	 */
	sscape_write(sscape, GA_INTENA_REG, 0x80);

	/*
	 * Initialize mixer
	 */
	sscape->midi_vol = 0;
	host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100);
	host_write_ctrl_unsafe(sscape->io_base, 0, 100);
	host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100);

	/*
	 * Now that we have successfully created this sound card,
	 * it is safe to store the pointer.
	 * NOTE: we only register the sound card's "destructor"
	 *       function now that our "constructor" has completed.
	 */
	card->private_free = soundscape_free;
	*rcardp = card;

	return 0;

	_release_card:
	snd_card_free(card);

	_release_dma:
	free_dma(dma[dev]);

	_release_region:
	release_and_free_resource(io_res);

	return err;
}