static int
ac97_read2 (void *devc_, int index)
{
  fm801_devc *devc = devc_;
  int idx;
  oss_native_word flags;
  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
  /*
   * Wait until the codec interface is not ready..
   */
  for (idx = 0; idx < 10000; idx++)
    {
      if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)))
	break;
      oss_udelay (10);
    }
  if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))
    {
      DDB (cmn_err (CE_WARN, "Secondary AC97 (read) not ready (1)\n"));
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return 0;
    }
  /* read command */
  OUTW (devc->osdev, index | (0x1 << 10) | (1 << 7), devc->base + AC97_CMD);
  for (idx = 0; idx < 10000; idx++)
    {
      if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)))
	break;
      oss_udelay (10);
    }
  /*
   * Wait until the codec interface is not ready..
   */
  if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))
    {
      DDB (cmn_err (CE_WARN, "Secondary AC97 (read) not ready(2)\n"));
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return 0;
    }
  for (idx = 0; idx < 10000; idx++)
    {
      if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 8))
	break;
      oss_udelay (10);
    }
  if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 8)))
    {
      cmn_err (CE_WARN, "Secondary AC97 (read) data not valid (2)\n");
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return 0;
    }
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
  return INW (devc->osdev, devc->base + AC97_DATA);
}
Beispiel #2
0
static int detect_mad16(void)
{
	unsigned char tmp, tmp2, bit;
	int i, port;

	/*
	 * Check that reading a register doesn't return bus float (0xff)
	 * when the card is accessed using password. This may fail in case
	 * the card is in low power mode. Normally at least the power saving
	 * mode bit should be 0.
	 */

	if ((tmp = mad_read(MC1_PORT)) == 0xff)
	{
		DDB(printk("MC1_PORT returned 0xff\n"));
		return 0;
	}
	for (i = 0xf8d; i <= 0xf98; i++)
		if (!c924pnp)
			DDB(printk("Port %0x (init value) = %0x\n", i, mad_read(i))) else
			DDB(printk("Port %0x (init value) = %0x\n", i-0x80, mad_read(i)));

	if (board_type == C930)
		return detect_c930();

	/*
	 * Now check that the gate is closed on first I/O after writing
	 * the password. (This is how a MAD16 compatible card works).
	 */

	if ((tmp2 = inb(MC1_PORT)) == tmp)	/* It didn't close */
	{
		DDB(printk("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
		return 0;
	}

	bit  = (c924pnp) ?     0x20 : 0x80;
	port = (c924pnp) ? MC2_PORT : MC1_PORT;

	tmp = mad_read(port);
	mad_write(port, tmp ^ bit);	/* Toggle a bit */
	if ((tmp2 = mad_read(port)) != (tmp ^ bit))	/* Compare the bit */
	{
		mad_write(port, tmp);	/* Restore */
		DDB(printk("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
		return 0;
	}
	mad_write(port, tmp);	/* Restore */
	return 1;		/* Bingo */
}
int
hdaudio_asus_m9_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group)
{
	DDB(cmn_err(CE_CONT, "hdaudio_asus_m9_mixer_init got called.\n"));

	corb_write (mixer, cad, 0x1b, 0, SET_EAPD, 0);

	return hdaudio_generic_mixer_init(dev, mixer, cad, top_group);
}
Beispiel #4
0
int probe_adlib(struct address_info *hw_config)
{
	if (check_region(hw_config->io_base, 4)) 
	{
		DDB(printk("opl3.c: I/O port %x already in use\n", hw_config->io_base));
		return 0;
	}
	return opl3_detect(hw_config->io_base, hw_config->osp);
}
static int
ac97_write2 (void *devc_, int index, int data)
{
  fm801_devc *devc = devc_;
  int idx;
  oss_native_word flags;
  MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
  /*
   * Wait until the codec interface is ready..
   */
  for (idx = 0; idx < 10000; idx++)
    {
      if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)))
	break;
      oss_udelay (10);
    }
  if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))
    {
      DDB (cmn_err (CE_WARN, "Secondary AC97 busy\n"));
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return OSS_EIO;
    }
  /* write data and address */
  OUTW (devc->osdev, data, devc->base + AC97_DATA);
  OUTW (devc->osdev, index | (0x1 << 10), devc->base + AC97_CMD);
  /*
   * Wait until the write command is completed..
   */
  for (idx = 0; idx < 1000; idx++)
    {
      if (!(INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9)))
	break;
      oss_udelay (10);
    }
  if (INW (devc->osdev, devc->base + AC97_CMD) & (1 << 9))
    {
      DDB (cmn_err (CE_WARN, "Secondary AC97 busy (1)\n"));
      MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
      return OSS_EIO;
    }
  MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
  return 0;
}
void *
yamaha_usb_midi_driver (ossusb_devc * usb_devc)
{
  ymhusb_devc *devc;
  int i;
  unsigned char *desc;
  int desc_len;
  int caps = MIDI_CAP_EXTERNAL;
  unsigned int devid;

  char *name = "Yamaha USB MIDI";

  if (usb_devc->dev_name != NULL)
    name = usb_devc->dev_name;

  if ((devc = PMALLOC (usb_devc->osdev, sizeof (*devc))) == NULL)
    {
      cmn_err (CE_WARN, "Yamaha MIDI: Out of memory\n");
      return NULL;
    }

  memset (devc, 0, sizeof (*devc));

  devc->unload_func = ymhusb_unload;
  devc->osdev = usb_devc->osdev;
  devc->usbdev = usb_devc->last_usbdev;
  MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
  devid = (usb_devc->vendor << 16) | usb_devc->product;

  DDB (cmn_err
       (CE_CONT, "Attaching Yamaha MIDI device %08x (%s)\n", devid, name));

  switch (devid)
    {
    case 0x0499101e:		/* PSR-K1 keyboard */
      caps |= MIDI_CAP_PTOP;
      break;
    }

  for (i = 0; i < 32; i++)
    if ((desc =
	 udi_usbdev_get_endpoint (devc->usbdev, 0, i, &desc_len)) != NULL)
      {
	if (desc[2] & 0x80)
	  {
	    add_input_device (devc, name, desc, caps);
	  }
	else
	  {
	    add_output_device (devc, name, desc, caps);
	  }
      }

  return devc;
}
int
hdaudio_asus_a7k_GPIO_init (int dev, hdaudio_mixer_t * mixer, int cad, int top_group)
{
        DDB(cmn_err(CE_CONT, "hdaudio_asus_a7k_GPIO_init got called.\n"));

        corb_write (mixer, cad, 0x01, 0, SET_GPIO_ENABLE, 3);
        corb_write (mixer, cad, 0x01, 0, SET_GPIO_DIR, 1);
        corb_write (mixer, cad, 0x01, 0, SET_GPIO_DATA, 1);

        return hdaudio_generic_mixer_init(dev, mixer, cad, top_group);
}
static int detect_ga(sscape_info * devc)
{
	unsigned char save;

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

	if (check_region(devc->base, 8))
		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)
	{
		DDB(printk("soundscape: Detect error A\n"));
		return 0;
	}
	outb((0x00), PORT(ODIE_ADDR));
	if (inb(PORT(ODIE_ADDR)) != 0x00)
	{
		DDB(printk("soundscape: Detect error B\n"));
		return 0;
	}
	outb((0xff), PORT(ODIE_ADDR));
	if (inb(PORT(ODIE_ADDR)) != 0x0f)
	{
		DDB(printk("soundscape: Detect error C\n"));
		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)
	{
		DDB(printk("soundscape: Detect error D (%x)\n", sscape_read(devc, 0)));
		return 0;
	}
	if (sscape_read(devc, 1) & 0x0f)
	{
		DDB(printk("soundscape: Detect error E\n"));
		return 0;
	}
	if (sscape_read(devc, 5) & 0x0f)
	{
		DDB(printk("soundscape: Detect error F\n"));
		return 0;
	}
	return 1;
}
void
HwStopDMA (allegro_devc * devc, unsigned char Direction)
{
  if (!Direction)
    WaveStream = &CaptureStream;
  else
    WaveStream = &PlaybackStream;

  SetState (devc, *WaveStream, KSSTATE_STOP);

  DDB (cmn_err (CE_WARN, "Wave%s DMA stopped\n", !Direction ? "In" : "Out"));
}
int
hdaudio_GPIO_init_1 (int dev, hdaudio_mixer_t * mixer, int cad, int top_group)
{
	DDB(cmn_err(CE_CONT, "hdaudio_GPIO_init_1 got called.\n"));

	/* Acer TravelMate 4060 and similar Aspire series, with ALC260 codec, need
	 * that we init GPIO to get internal speaker and headphone jack working. */
	corb_write(mixer, cad, 0x01, 0, SET_GPIO_ENABLE, 1);
	corb_write(mixer, cad, 0x01, 0, SET_GPIO_DIR, 1);
	corb_write(mixer, cad, 0x01, 0, SET_GPIO_DATA, 1);
  
	return hdaudio_generic_mixer_init(dev, mixer, cad, top_group);
}
Beispiel #11
0
int
sndtable_init_card(int unit, struct address_info * hw_config)
{
    int     i, n = num_sound_cards;
    struct card_info *ci = snd_installed_cards ;

    DDB(printf("sndtable_init_card(%d) entered\n", unit));

    if (!unit) {
        sndtable_init() ;
        return TRUE;
    }
    for (i = 0; i < n && ci->card_type; ci++, i++)
        if (ci->card_type == unit) {
            int             drv;

            ci->config.io_base = hw_config->io_base;
            ci->config.irq = hw_config->irq;
            ci->config.dma = hw_config->dma;
            ci->config.dma2 = hw_config->dma2;
            ci->config.name = hw_config->name;
            ci->config.always_detect = hw_config->always_detect;
            ci->config.card_subtype = hw_config->card_subtype;
            ci->config.osp = hw_config->osp;

            if ((drv = snd_find_driver(ci->card_type)) == -1)
                ci->enabled = 0; /* Mark not fnd */
            else {
                DDB(printf("Located card - calling attach routine\n"));
                sound_drivers[drv].attach(hw_config) ;
                DDB(printf("attach routine finished\n"));
            }
            start_services();
            return TRUE;
        }
    DDB(printf("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
               unit, num_sound_cards));
    return FALSE;
}
Beispiel #12
0
static int wss_init(struct address_info *hw_config)
{
	int ad_flags = 0;

	/*
	 *    Verify the WSS parameters
	 */

	if (check_region(hw_config->io_base, 8))
	{
		printk(KERN_ERR "MSS: I/O port conflict\n");
		return 0;
	}
	if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
		return 0;
	/*
	 * Check if the IO port returns valid signature. The original MS Sound
	 * system returns 0x04 while some cards (AudioTrix Pro for example)
	 * return 0x00.
	 */

	if ((inb(hw_config->io_base + 3) & 0x3f) != 0x04 &&
	    (inb(hw_config->io_base + 3) & 0x3f) != 0x00)
	{
		DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3)));
		return 0;
	}
	if (hw_config->irq > 11)
	{
		printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
		return 0;
	}
	if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
	{
		printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma);
		return 0;
	}
	/*
	 * Check that DMA0 is not in use with a 8 bit board.
	 */

	if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
	{
		printk("MSS: Can't use DMA0 with a 8 bit card/slot\n");
		return 0;
	}
	if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
		printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
	return 1;
}
static void __exit unload_gus(struct address_info *hw_config)
{
	DDB(printk("unload_gus(%x)\n", hw_config->io_base));

	gus_wave_unload(hw_config);

	release_region(hw_config->io_base, 16);
	release_region(hw_config->io_base + 0x100, 12);		/* 0x10c-> is MAX */
	free_irq(hw_config->irq, hw_config);

	sound_free_dma(hw_config->dma);

	if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
		sound_free_dma(hw_config->dma2);
}
Beispiel #14
0
static int reset_uart401(uart401_devc * devc)
{
	int ok, timeout, n;

	/*
	 * Send the RESET command. Try again if no success at the first time.
	 */

	ok = 0;

	for (n = 0; n < 2 && !ok; n++)
	{
		for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--);
		devc->input_byte = 0;
		uart401_cmd(devc, MPU_RESET);

		/*
		 * Wait at least 25 msec. This method is not accurate so let's make the
		 * loop bit longer. Cannot sleep since this is called during boot.
		 */

		for (timeout = 50000; timeout > 0 && !ok; timeout--)
		{
			if (devc->input_byte == MPU_ACK)	/* Interrupt */
				ok = 1;
			else if (input_avail(devc))
			{
				if (uart401_read(devc) == MPU_ACK)
					ok = 1;
			}
		}
	}


	if (ok)
	{
		DEB(printk("Reset UART401 OK\n"));
	}
	else
		DDB(printk("Reset UART401 failed - No hardware detected.\n"));

	if (ok)
		uart401_input_loop(devc);	/*
						 * Flush input before enabling interrupts
						 */

	return ok;
}
Beispiel #15
0
int
probe_trix_wss (struct address_info *hw_config)
{
  /*
     * Check if the IO port returns valid signature. The original MS Sound
     * system returns 0x04 while some cards (AudioTriX Pro for example)
     * return 0x00.
   */
  if (!trix_set_wss_port (hw_config))
    return 0;

  if ((INB (hw_config->io_base + 3) & 0x3f) != 0x00)
    {
      DDB (printk ("No MSS signature detected on port 0x%x\n", hw_config->io_base));
      return 0;
    }

  if (hw_config->irq > 11)
    {
      printk ("AudioTriX: Bad WSS IRQ %d\n", hw_config->irq);
      return 0;
    }

  if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
    {
      printk ("AudioTriX: Bad WSS DMA %d\n", hw_config->dma);
      return 0;
    }

  /*
     * Check that DMA0 is not in use with a 8 bit board.
   */

  if (hw_config->dma == 0 && INB (hw_config->io_base + 3) & 0x80)
    {
      printk ("AudioTriX: Can't use DMA0 with a 8 bit card\n");
      return 0;
    }

  if (hw_config->irq > 7 && hw_config->irq != 9 && INB (hw_config->io_base + 3) & 0x80)
    {
      printk ("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq);
      return 0;
    }

  return ad1848_detect (hw_config->io_base + 4);
}
Beispiel #16
0
int probe_uart401(struct address_info *hw_config, struct module *owner)
{
	uart401_devc *devc;
	char *name = "MPU-401 (UART) MIDI";
	int ok = 0;
	unsigned long flags;

	DDB(printk("Entered probe_uart401()\n"));

	/* Default to "not found" */
	hw_config->slots[4] = -1;

	if (!request_region(hw_config->io_base, 4, "MPU-401 UART")) {
		printk(KERN_INFO "uart401: could not request_region(%d, 4)\n", hw_config->io_base);
		return 0;
	}

	devc = kmalloc(sizeof(uart401_devc), GFP_KERNEL);
	if (!devc) {
		printk(KERN_WARNING "uart401: Can't allocate memory\n");
		goto cleanup_region;
	}

	devc->base = hw_config->io_base;
	devc->irq = hw_config->irq;
	devc->osp = hw_config->osp;
	devc->midi_input_intr = NULL;
	devc->opened = 0;
	devc->input_byte = 0;
	devc->my_dev = 0;
	devc->share_irq = 0;
	spin_lock_init(&devc->lock);

	spin_lock_irqsave(&devc->lock,flags);	
	ok = reset_uart401(devc);
	spin_unlock_irqrestore(&devc->lock,flags);

	if (!ok)
		goto cleanup_devc;

	if (hw_config->name)
		name = hw_config->name;

	if (devc->irq < 0) {
		devc->share_irq = 1;
		devc->irq *= -1;
	} else
		devc->share_irq = 0;

	if (!devc->share_irq)
		if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0) {
			printk(KERN_WARNING "uart401: Failed to allocate IRQ%d\n", devc->irq);
			devc->share_irq = 1;
		}
	devc->my_dev = sound_alloc_mididev();
	enter_uart_mode(devc);

	if (devc->my_dev == -1) {
		printk(KERN_INFO "uart401: Too many midi devices detected\n");
		goto cleanup_irq;
	}
	conf_printf(name, hw_config);
	midi_devs[devc->my_dev] = kmemdup(&uart401_operations,
					  sizeof(struct midi_operations),
					  GFP_KERNEL);
	if (!midi_devs[devc->my_dev]) {
		printk(KERN_ERR "uart401: Failed to allocate memory\n");
		goto cleanup_unload_mididev;
	}

	if (owner)
		midi_devs[devc->my_dev]->owner = owner;
	
	midi_devs[devc->my_dev]->devc = devc;
	midi_devs[devc->my_dev]->converter = kmemdup(&std_midi_synth,
						     sizeof(struct synth_operations),
void hdaudio_si3055_endpoint_init(hdaudio_mixer_t *mixer, int cad)
{
  codec_t *codec = mixer->codecs[cad];  /* Modem codec */
  widget_t *widget;                     /* MFG widget */
  hdaudio_endpointinfo_t *endpoint;
  unsigned int a, b;      /* Used for reading data. */
  int tmout;              /* Timeout counter. */

  /* Output and input stream numbers. */
  int playback_stream_num, recording_stream_num;

  
  DDB(cmn_err(CE_CONT, "hdaudio_si3055_endpoint_init got called.\n"));

  /* Reset the modem codec. */
  corb_write(mixer, cad, 0x00, 0, SET_CODEC_RESET, 0);
  corb_write(mixer, cad, codec->afg, 0, SET_CONVERTER, IDDLE_STREAM << 4);
  corb_write(mixer, cad, codec->afg, 0, SET_CONVERTER_FORMAT, 0);
  
  /* Set 9600Hz as the initial line sampling rate.
   * It can be changed later when desired.
   */
  SI3055_REG_SET(mixer, cad, SI3055_LINE_RATE, 9600);
  
  /* Assign the "unused" value to the playback and recording
   * stream descriptors (ref. HDAudio_03.pdf, page 40).
   */
  SI3055_REG_SET(mixer, cad, SI3055_HDA_STREAMS, 0x0000);
  
  /* Write 0x0000 to the Extended Modem Status & Control register
   * to power up the modem (ref. si3038.pdf, page 22).
   */
  SI3055_REG_SET(mixer, cad, SI3055_EXT_MODEM_STATUS, 0x0000);
  
  /* Wait for the modem to complete power up. The lower 8 bits
   * indicate that it is ready (ref. si3038.pdf, page 22).
   */
  tmout = 10;
  do
    {
      SI3055_REG_GET(mixer, cad, SI3055_EXT_MODEM_STATUS, &a, &b);
      DDB(cmn_err(CE_CONT, "si3055: ext modem status: %04x.\n", a));
      oss_udelay(1000);
    }
    while(((a & 0xf) == 0) && --tmout);
  
  if ((a & 0xf) == 0)
    {
      cmn_err(CE_WARN, "si3055: power up timeout (status: %04x).\n", a);
    }
  
  /* This register contains 0x1fff after reset. We need to set it
   * to zero to get the modem working. No corresponding register
   * could be found in the Si3038 datasheet.
   */
  SI3055_REG_SET(mixer, cad, SI3055_GPIO_CONFIG, 0x0000);

  /* Program line interface parameters. The register value after
   * a reset is 0xF010. Set it to 0x0010 to unmute the analog
   * receive and transmit paths.
   */
  SI3055_REG_SET(mixer, cad, SI3055_LINE_CONFIG, 0x0010);
      
  /* Setup the widget info. */
  widget = &codec->widgets[codec->afg];
  widget->endpoint = &codec->inendpoints[0];
  widget->sizes = 0x20000; /* 16 bits */
  strcpy(widget->name, "modem");

  /* Setup the output endpoint. */
  codec->num_outendpoints = 1;
  endpoint = &codec->outendpoints[0];
  endpoint->ix = 0;
  endpoint->iddle_stream = 0;
  endpoint->cad = cad;
  endpoint->base_wid = codec->afg;
  endpoint->recsrc_wid = endpoint->volume_wid = -1;
  endpoint->nrates = 3;
  endpoint->rates[0] = 8000;
  endpoint->rates[1] = 9600;
  endpoint->rates[2] = 16000;
  endpoint->name = widget->name;
  endpoint->channels = 1;
  endpoint->is_digital = 0;
  endpoint->is_modem = 1;
  endpoint->sizemask = widget->sizes;
  endpoint->fmt_mask = AFMT_S16_LE;
  endpoint->afg = codec->afg;
  endpoint->min_rate = 8000;
  endpoint->max_rate = 16000;
  
  /* Setup the input endpoint. */
  codec->num_inendpoints = 1;
  memcpy(&codec->inendpoints[0], endpoint, sizeof(*endpoint));

  /* Choose stream numbers for output and input streams. */
  playback_stream_num = ++mixer->num_outendpoints;
  endpoint->stream_number = endpoint->default_stream_number = playback_stream_num;

  endpoint = &codec->inendpoints[0];
  recording_stream_num = ++mixer->num_inendpoints;
  endpoint->stream_number = endpoint->default_stream_number = recording_stream_num;

  /* Setup the stream numbers. */
  SI3055_REG_SET(mixer, cad, SI3055_HDA_STREAMS, ((playback_stream_num  << 4) << 8) |
                                                  (recording_stream_num << 4));
}
Beispiel #18
0
static int detect_c930(void)
{
	unsigned char   tmp = mad_read(MC1_PORT);

	if ((tmp & 0x06) != 0x06)
	{
		DDB(printk("Wrong C930 signature (%x)\n", tmp));
		/* return 0; */
	}
	mad_write(MC1_PORT, 0);

	if (mad_read(MC1_PORT) != 0x06)
	{
		DDB(printk("Wrong C930 signature2 (%x)\n", tmp));
		/* return 0; */
	}
	mad_write(MC1_PORT, tmp);	/* Restore bits */

	mad_write(MC7_PORT, 0);
	if ((tmp = mad_read(MC7_PORT)) != 0)
	{
		DDB(printk("MC7 not writable (%x)\n", tmp));
		return 0;
	}
	mad_write(MC7_PORT, 0xcb);
	if ((tmp = mad_read(MC7_PORT)) != 0xcb)
	{
		DDB(printk("MC7 not writable2 (%x)\n", tmp));
		return 0;
	}

	tmp = mad_read(MC0_PORT+18);
	if (tmp == 0xff || tmp == 0x00)
		return 1;
	/* We probably have a C931 */
	DDB(printk("Detected C931 config=0x%02x\n", tmp));
	c931_detected = 1;

	/*
         * We cannot configure the chip if it is in PnP mode.
         * If we have a CSN assigned (bit 8 in MC13) we first try
         * a software reset, then a software power off, finally
         * Clearing PnP mode. The last option is not
	 * Bit 8 in MC13 
         */
	if ((mad_read(MC0_PORT+13) & 0x80) == 0)
		return 1;

	/* Software reset */
	mad_write(MC9_PORT, 0x02);
	mad_write(MC9_PORT, 0x00);

	if ((mad_read(MC0_PORT+13) & 0x80) == 0)
		return 1;
	
	/* Power off, and on again */
	mad_write(MC9_PORT, 0xc2);
	mad_write(MC9_PORT, 0xc0);

	if ((mad_read(MC0_PORT+13) & 0x80) == 0)
		return 1;
	
#if 0	
	/* Force off PnP mode. This is not recommended because
	 * the PnP bios will not recognize the chip on the next
	 * warm boot and may assignd different resources to other
	 * PnP/PCI cards.
	 */
	mad_write(MC0_PORT+17, 0x04);
#endif
	return 1;
}
int
oss_als3xx_attach (oss_device_t * osdev)
{
  unsigned char pci_irq_line, pci_revision;
  unsigned short pci_command, vendor, device;
  unsigned int pci_ioaddr;
  int err;
  als300_devc *devc;

  DDB (cmn_err (CE_WARN, "Entered ALS ALS300 probe routine\n"));


  pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor);
  pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision);
  pci_read_config_word (osdev, PCI_COMMAND, &pci_command);
  pci_read_config_word (osdev, PCI_DEVICE_ID, &device);
  pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line);
  pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr);

  if (vendor != ALS_VENDOR_ID || (device != ALS_300 && device != ALS_300P))
    return 0;

  DDB (cmn_err (CE_WARN, "rev %x I/O base %04x\n", pci_revision, pci_ioaddr));

  if (pci_ioaddr == 0)
    {
      cmn_err (CE_WARN, "I/O address not assigned by BIOS.\n");
      return 0;
    }

  if (pci_irq_line == 0)
    {
      cmn_err (CE_WARN, "IRQ not assigned by BIOS (%d).\n", pci_irq_line);
      return 0;
    }

  if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL)
    {
      cmn_err (CE_WARN, "Out of memory\n");
      return 0;
    }

  devc->osdev = osdev;
  osdev->devc = devc;
  devc->open_mode = 0;

  devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr);
  /* Remove I/O space marker in bit 0. */
  devc->base &= ~3;

  devc->irq = pci_irq_line;
  devc->mpu_base = als300_mpu_base;

  pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
  pci_write_config_word (osdev, PCI_COMMAND, pci_command);


  switch (device)
    {
    case ALS_300:
      devc->model = MDL_ALS300;
      devc->chip_name = "Avance Logic ALS300";
      devc->chip_rev = pci_revision;
      break;

    case ALS_300P:
      devc->model = MDL_ALS300PLUS;
      devc->chip_name = "Avance Logic ALS300+";
      devc->chip_rev = pci_revision;
      break;
    }

  MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
  MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1);

  oss_register_device (osdev, devc->chip_name);

  if ((err = oss_register_interrupts (devc->osdev, 0, als300intr, NULL)) < 0)
    {
      cmn_err (CE_WARN, "Can't allocate IRQ%d, err=%d\n", pci_irq_line, err);
      return 0;
    }

  return init_als300 (devc);	/* Detected */
}
Beispiel #20
0
int
sndtable_probe(int unit, struct address_info * hw_config)
{
    int  i, sel = -1, n = num_sound_cards;
    struct card_info *ci = snd_installed_cards ;

    DDB(printf("-- sndtable_probe(%d)\n", unit));


    /*
     * for some reason unit 0 always succeeds ?
     */
    if (!unit)
        return TRUE;

    sound_started = 1;

    for (i=0; i<n && sel== -1 && ci->card_type; ci++, i++)
        if ( (ci->enabled) && (ci->card_type == unit) ) {
            /* DDB(printf("-- found card %d\n", i) ); */
            sel = i; /* and break */
        }

    /*
     * not found. Creates a new entry in the table for this unit.
     */
    if (sel == -1 && num_sound_cards < max_sound_cards) {
        int   i;

        i = sel = (num_sound_cards++);
        DDB(printf("-- installing card %d\n", i) );

        ci = &snd_installed_cards[sel] ;
        ci->card_type = unit;
        ci->enabled = 1;
    }
    /* DDB(printf("-- installed card %d\n", sel) ); */
    if (sel != -1) {
        int   drv;

        ci->config.io_base = hw_config->io_base;
        ci->config.irq = hw_config->irq;
        ci->config.dma = hw_config->dma;
        ci->config.dma2 = hw_config->dma2;
        ci->config.name = hw_config->name;
        ci->config.always_detect = hw_config->always_detect;
        ci->config.card_subtype = hw_config->card_subtype;
        ci->config.osp = hw_config->osp;

        if ((drv = snd_find_driver(ci->card_type)) == -1) {
            ci->enabled = 0;
            DDB(printf("Failed to find driver\n"));
            return FALSE;
        }
        DDB(printf("-- Driver name '%s' probe 0x%08x\n",
                   sound_drivers[drv].name, sound_drivers[drv].probe));

        hw_config->card_subtype =
            ci->config.card_subtype = sound_drivers[drv].card_subtype;

        if (sound_drivers[drv].probe(hw_config)) {
            DDB(printf("-- Hardware probed OK\n"));
            return TRUE;
        }
        DDB(printf("-- Failed to find hardware\n"));
        ci->enabled = 0;	/* mark as not detected */
        return FALSE;
    }
    return FALSE;
}
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 #22
0
static int chip_detect(void)
{
	int i;

	/*
	 *    Then try to detect with the old password
	 */
	board_type = C924;

	DDB(printk("Detect using password = 0xE5\n"));
	
	if (!detect_mad16())	/* No luck. Try different model */
	{
		board_type = C928;

		DDB(printk("Detect using password = 0xE2\n"));

		if (!detect_mad16())
		{
			board_type = C929;

			DDB(printk("Detect using password = 0xE3\n"));

			if (!detect_mad16())
			{
				if (inb(PASSWD_REG) != 0xff)
					return 0;

				/*
				 * First relocate MC# registers to 0xe0e/0xe0f, disable password 
				 */

				outb((0xE4), PASSWD_REG);
				outb((0x80), PASSWD_REG);

				board_type = C930;

				DDB(printk("Detect using password = 0xE4\n"));

				for (i = 0xf8d; i <= 0xf93; i++)
					DDB(printk("port %03x = %02x\n", i, mad_read(i)));
                                if(!detect_mad16()) {

				  /* The C931 has the password reg at F8D */
				  outb((0xE4), 0xF8D);
				  outb((0x80), 0xF8D);
				  DDB(printk("Detect using password = 0xE4 for C931\n"));

				  if (!detect_mad16()) {
				    board_type = C924;
				    c924pnp++;
				    DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
				    if (!detect_mad16()) {
				      c924pnp=0;
				      return 0;
				    }
				  
				    DDB(printk("mad16.c: 82C924 PnP detected\n"));
				  }
				}
				else
				  DDB(printk("mad16.c: 82C930 detected\n"));
			} else
				DDB(printk("mad16.c: 82C929 detected\n"));
		} else {
			unsigned char model;

			if (((model = mad_read(MC3_PORT)) & 0x03) == 0x03) {
				DDB(printk("mad16.c: Mozart detected\n"));
				board_type = MOZART;
			} else {
				DDB(printk("mad16.c: 82C928 detected???\n"));
				board_type = C928;
			}
		}
	}
	return 1;
}
int
hdaudio_vaio_vgn_mixer_init (int dev, hdaudio_mixer_t * mixer, int cad,
			     int top_group)
{
  int ctl = 0;

  DDB (cmn_err (CE_CONT, "hdaudio_vaio_vgn_mixer_init got called.\n"));

  HDA_OUTAMP_F (0x05, top_group, "speaker", 90, MIXF_MAINVOL);
  /* We sync the volume of the headphone DAC to the speaker DAC */
#if 1
  HDA_OUTAMP_F (0x02, top_group, "headphone", 90, MIXF_MAINVOL);
#endif


  HDA_SETSELECT (0x0f, 0);	/* Int speaker mode */
  HDA_SETSELECT (0x14, 1);	/* Int mic mode */

  /* Handle PIN widgets */
  {
    int n, group, pin_group;

    n = 0;

    HDA_GROUP (pin_group, top_group, "jack");

    if (HDA_PIN_GROUP (0x0a, group, pin_group, "headphone", n, "jack", 4))	/* Pin widget 0x0a */
      {
	/* Src 0x2=pcm */
	if (HDA_PINSELECT (0x0a, ctl, group, "mode", -1))
	  HDA_CHOICES (ctl, "pcm-out input");
	HDA_OUTMUTE (0x0a, group, "mute", UNMUTE);
      }

    if (HDA_PIN_GROUP (0x0b, group, pin_group, "black", n, "jack", 4))	/* Pin widget 0x0b */
      {
	/* Src 0x4=pcm */
	if (HDA_PINSELECT (0x0b, ctl, group, "mode", -1))
	  HDA_CHOICES (ctl, "pcm-out input");
	HDA_OUTMUTE (0x0b, group, "mute", UNMUTE);

	/* Widget 0x04 (pcm) */
	HDA_OUTAMP (0x04, group, "-", 90);
      }

    if (HDA_PIN_GROUP (0x0c, group, pin_group, "black", n, "jack", 4))	/* Pin widget 0x0c */
      {
	/* Src 0x3=pcm */
	if (HDA_PINSELECT (0x0c, ctl, group, "mode", -1))
	  HDA_CHOICES (ctl, "pcm-out input");
	HDA_OUTMUTE (0x0c, group, "mute", UNMUTE);

	/* Widget 0x03 (pcm) */
	HDA_OUTAMP (0x03, group, "-", 90);
      }

    if (HDA_PIN_GROUP (0x0d, group, pin_group, "red", n, "jack", 4))	/* Pin widget 0x0d */
      {
	/* Src 0x2=pcm */
	if (HDA_PINSELECT (0x0d, ctl, group, "mode", -1))
	  HDA_CHOICES (ctl, "pcm-out input");
	HDA_OUTMUTE (0x0d, group, "mute", UNMUTE);
      }

    if (HDA_PIN_GROUP (0x0e, group, pin_group, "black", n, "jack", 4))	/* Pin widget 0x0e */
      {
	if (HDA_PINSELECT (0x0e, ctl, group, "mode", -1))
	  HDA_CHOICES (ctl, "input");
      }
  }
  /* Handle ADC widgets */
  {
    int n, group, rec_group;

    n = 0;

    HDA_GROUP (rec_group, top_group, "record");

    if (HDA_ADC_GROUP (0x06, group, rec_group, "rec1", n, "record", 4))	/* ADC widget 0x06 */
      {
	/* Src 0x7=rec */

	/* Widget 0x07 (rec) */
	/* Src 0xe=black */
	HDA_INAMP_F (0x07, 0, group, "black", 80, MIXF_RECVOL);	/* From widget 0x0e */
      }

    if (HDA_ADC_GROUP (0x08, group, rec_group, "rec", n, "record", 8))	/* ADC widget 0x08 */
      {
	/* Src 0x9=rec */

	/* Widget 0x09 (rec) */
	/* Src 0x15=rec */
	HDA_INAMP_F (0x09, 0, group, "rec", 80, MIXF_RECVOL);	/* From widget 0x15 */

	/* Widget 0x15 (rec) */
	/* Src 0xa=black */
	/* Src 0xd=red */
	/* Src 0x14=int-mic */
	/* Src 0x2=pcm */
	if (HDA_SELECT (0x15, "src", ctl, group, -1))
	  {
	    HDA_CHOICES (ctl, "headphone mic int-mic pcm");
	  }
	HDA_OUTAMP (0x15, group, "micboost", 0);
      }

    if (HDA_ADC_GROUP (0x12, group, rec_group, "spdifin", n, "record", 4))	/* ADC widget 0x12 */
      {
	/* Src 0x13=speaker */
      }
  }
  /* Handle misc widgets */
  {
#if 0
    if (HDA_MISC_GROUP (0x16, group, misc_group, "beep", n, "misc", 8))	/* Misc widget 0x16 */
      {
	HDA_OUTAMP (0x16, group, "-", 90);
      }
#endif
  }
  return 0;
}
int
oss_fmedia_attach (oss_device_t * osdev)
{
  unsigned char pci_irq_line, pci_revision;
  unsigned short pci_command, vendor, device;
  unsigned int pci_ioaddr;
  int err;
  fm801_devc *devc;

  DDB (cmn_err (CE_WARN, "Entered FM801 FM801 probe routine\n"));

  pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor);
  pci_read_config_word (osdev, PCI_DEVICE_ID, &device);

  if (vendor != FORTEMEDIA_VENDOR_ID || device != FORTEMEDIA_FM801)
    return 0;

  pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision);
  pci_read_config_word (osdev, PCI_COMMAND, &pci_command);
  pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line);
  pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr);

  DDB (cmn_err (CE_WARN, "FM801 I/O base %04x\n", pci_ioaddr));

  if (pci_irq_line == 0)
    {
      cmn_err (CE_WARN, "IRQ not assigned by BIOS (%d). Can't continue\n",
	       pci_irq_line);
      return 0;
    }

  if (pci_ioaddr == 0)
    {
      cmn_err (CE_WARN, "I/O address not assigned by BIOS.\n");
      return 0;
    }

  if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL)
    {
      cmn_err (CE_WARN, "Out of memory\n");
      return 0;
    }
  devc->osdev = osdev;
  osdev->devc = devc;

  devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr);

  /* Remove I/O space marker in bit 0. */
  devc->base &= ~3;
  devc->mpu_irq = fmedia_mpu_irq;
  devc->mpu_base = devc->base + 0x30;
  pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
  pci_write_config_word (osdev, PCI_COMMAND, pci_command);

  switch (pci_revision)
    {
    case 0xb1:
      devc->model = MDL_FM801AS;
      devc->chip_name = "ForteMedia FM801-AS";
      break;
    case 0xb2:
      devc->model = MDL_FM801AU;
      devc->chip_name = "ForteMedia FM801-AU";
      break;
    }

  oss_register_device (osdev, devc->chip_name);
  if ((err = oss_register_interrupts (osdev, 0, fm801intr, NULL)) < 0)
    {
      cmn_err (CE_WARN, "Error installing interrupt handler: %x\n", err);
      return 0;
    }

  MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
  MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1);

  return init_fm801 (devc);	/* Detected */
}
Beispiel #25
0
int probe_mad16(struct address_info *hw_config)
{
	int i;
	static int valid_ports[] = 
	{
		0x530, 0xe80, 0xf40, 0x604
	};
	unsigned char tmp;
	unsigned char cs4231_mode = 0;

	int ad_flags = 0;

	if (already_initialized)
		return 0;

	mad16_osp = hw_config->osp;

	/*
	 *    Check that all ports return 0xff (bus float) when no password
	 *      is written to the password register.
	 */

	DDB(printk("--- Detecting MAD16 / Mozart ---\n"));
	if (!chip_detect())
		return 0;

	if (board_type == C930)
		return init_c930(hw_config);


	for (i = 0xf8d; i <= 0xf93; i++)
		if (!c924pnp)
			DDB(printk("port %03x = %02x\n", i, mad_read(i))) else
			DDB(printk("port %03x = %02x\n", i-0x80, mad_read(i)));

/*
 * Set the WSS address
 */

	tmp = (mad_read(MC1_PORT) & 0x0f) | 0x80;	/* Enable WSS, Disable SB */

	for (i = 0; i < 5; i++)
	{
		if (i > 3)	/* Not a valid port */
		{
			printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
			return 0;
		}
		if (valid_ports[i] == hw_config->io_base)
		{
			tmp |= i << 4;	/* WSS port select bits */
			break;
		}
	}

	/*
	 * Set optional CD-ROM and joystick settings.
	 */

	tmp &= ~0x0f;
#if defined(MAD16_CONF)
	tmp |= ((MAD16_CONF) & 0x0f);	/* CD-ROM and joystick bits */
#endif
	mad_write(MC1_PORT, tmp);

#if defined(MAD16_CONF) && defined(MAD16_CDSEL)
	tmp = MAD16_CDSEL;
#else
	tmp = mad_read(MC2_PORT);
#endif

#ifdef MAD16_OPL4
	tmp |= 0x20;		/* Enable OPL4 access */
#endif

	mad_write(MC2_PORT, tmp);
	mad_write(MC3_PORT, 0xf0);	/* Disable SB */

	if (board_type == C924)	/* Specific C924 init values */
	{
		mad_write(MC4_PORT, 0xA0);
		mad_write(MC5_PORT, 0x05);
		mad_write(MC6_PORT, 0x03);
	}
	if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
		return 0;

	if (ad_flags & (AD_F_CS4231 | AD_F_CS4248))
		cs4231_mode = 0x02;	/* CS4248/CS4231 sync delay switch */

	if (board_type == C929)
	{
		mad_write(MC4_PORT, 0xa2);
		mad_write(MC5_PORT, 0xA5 | cs4231_mode);
		mad_write(MC6_PORT, 0x03);	/* Disable MPU401 */
	}
	else
	{
		mad_write(MC4_PORT, 0x02);
		mad_write(MC5_PORT, 0x30 | cs4231_mode);
	}

	for (i = 0xf8d; i <= 0xf93; i++) if (!c924pnp)
		DDB(printk("port %03x after init = %02x\n", i, mad_read(i))) else
		DDB(printk("port %03x after init = %02x\n", i-0x80, mad_read(i)));
	wss_init(hw_config);

	return 1;
}
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;	
}