Google
 

Open Sound System
The Hitchhiker's Guide to OSS 4.1 Internals

Do you have problems with sound/audio application development? Don't panic! Click here for help!

oss_envy24ht/envy24ht_revo71.c

Low level routines for M Audio Revolution 7.1

Description




This file is part of Open Sound System.

Copyright (C) 4Front Technologies 1996-2008.

This this source file is released under GPL v2 license (no other versions). See the COPYING file included in the main directory of this source distribution for the license terms and conditions.


#include "oss_envy24ht_cfg.h"

#include "spdif.h"
#include "envy24ht.h"

#define BIT(x) (1<<(x))

#define CCLK	(1<<1)
#define CDIN	(1<<2)		/* Currently not connected */
#define CDTI	(1<<3)
#define CSDIG	(1<<4)
#define CSN1	(1<<5)
#define CSN2	(1<<6)

#define WRITEMASK 	(CSN1|CSN2|CDTI|CCLK)

#define DAC1 0x01		/* 2ch Front DAC (AK4381) */
#define DAC2 0x03		/* 6ch Surround DAC (AK4355) */


static void
writereg (envy24ht_devc * devc, int csn, int chip, unsigned char reg,
	  unsigned char val)
{
  int i;
  unsigned short v, tmp;

  tmp = INW (devc->osdev, devc->ccs_base + 0x14) & ~(csn | CCLK | CDTI);
  OUTW (devc->osdev, tmp, devc->ccs_base + 0x14);

  reg = (reg & 0x1f) | 0x20 | (chip << 6);	/* Chip address (variable), write */
  /* Address bits */

  for (i = 7; i >= 0; i--)
    {
      v = (reg & (1 << i)) ? CDTI : 0;
      OUTW (devc->osdev, v | tmp, devc->ccs_base + 0x14);	/* Tack */
      OUTW (devc->osdev, v | CCLK | tmp, devc->ccs_base + 0x14);	/* Tick */
    }

  /* Data bits */

  for (i = 7; i >= 0; i--)
    {
      v = (val & (1 << i)) ? CDTI : 0;
      OUTW (devc->osdev, v | tmp, devc->ccs_base + 0x14);	/* Tack */
      OUTW (devc->osdev, v | CCLK | tmp, devc->ccs_base + 0x14);	/* Tick */
    }

  OUTW (devc->osdev, v | tmp, devc->ccs_base + 0x14);	/* Tack */
  OUTW (devc->osdev, tmp | csn | CDTI | CCLK, devc->ccs_base + 0x14);	/* Release */

}

static void
writedac1 (envy24ht_devc * devc, unsigned char reg, unsigned char data)
{
  writereg (devc, CSN1, DAC1, reg, data);
  devc->dac1val[reg] = data;
}

static void
writedac2 (envy24ht_devc * devc, unsigned char reg, unsigned char data)
{
  writereg (devc, CSN2, DAC2, reg, data);
  devc->dac2val[reg] = data;
}

static void
revo71_mute (envy24ht_devc * devc, int mute)
{
  if (mute)
    {
      writedac1 (devc, 1, devc->dac1val[1] | BIT (0));
      writedac2 (devc, 1, devc->dac2val[1] | BIT (1));
      oss_udelay (1000);
/*      OUTB (devc->osdev, INB (devc->osdev, devc->ccs_base + 0x1e) & ~BIT(22-16), */
/*          devc->ccs_base + 0x1e); */
    }
  else
    {
/*      OUTB (devc->osdev, INB (devc->osdev, devc->ccs_base + 0x1e) | ~BIT(22-16), */
/*          devc->ccs_base + 0x1e); */
      oss_udelay (1000);
      writedac1 (devc, 1, devc->dac1val[1] & ~BIT (0));
      writedac2 (devc, 1, devc->dac2val[1] & ~BIT (1));
    }
}

static void
revo71_card_init (envy24ht_devc * devc)
{
  int i;

  OUTL (devc->osdev, WRITEMASK | 0x400000, devc->ccs_base + 0x18);	/* GPIO direction */
  OUTW (devc->osdev, ~WRITEMASK, devc->ccs_base + 0x16);	/* GPIO write mask */
  OUTB (devc->osdev, 0x40, devc->ccs_base + 0x1f);
  OUTW (devc->osdev, WRITEMASK, devc->ccs_base + 0x14);	/* Initial bit state */

  OUTB (devc->osdev, 0xff, devc->ccs_base + 0x1a);	/* GPIO direction for bits 16:22 */
  OUTB (devc->osdev, 0x00, devc->ccs_base + 0x1f);	/* GPIO mask for bits 16:22 */
  OUTB (devc->osdev, 0xff, devc->ccs_base + 0x1e);	/* GPIO data for bits 16:22 */

#if 0
  for (i = 0; i < 7; i++)
    {
      OUTW (devc->osdev, 1 << i, devc->ccs_base + 0x14);	/* Test bit */
      OUTW (devc->osdev, 0, devc->ccs_base + 0x14);	/* Test bit */
    }
#endif

  OUTW (devc->osdev, WRITEMASK, devc->ccs_base + 0x14);	/* Initial bit state */
  oss_udelay (10);

  revo71_mute (devc, 1);

Init front DAC (AK4381)

  writedac1 (devc, 0x00, 0x0c);
  writedac1 (devc, 0x01, 0x03);
  writedac1 (devc, 0x02, 0x00);

  writedac1 (devc, 0x03, 0xff);	/* Initial volume */
  writedac1 (devc, 0x04, 0xff);	/* Initial volume */

  writedac1 (devc, 0x00, 0x0f);

Init surround DAC (AK4355)

  writedac2 (devc, 0x01, 0x02);
  writedac2 (devc, 0x00, 0x06);
  oss_udelay (10);
  writedac2 (devc, 0x02, 0x0e);
  writedac2 (devc, 0x03, 0x01);

  for (i = 4; i < 10; i++)
    writedac2 (devc, i, 0xff);	/* Initial volumes */
  writedac2 (devc, 0x0a, 0x00);

  writedac2 (devc, 0x01, 0x01);
  revo71_mute (devc, 0);
}

static void
revo71_set_rate (envy24ht_devc * devc)
{
  int rate = devc->speed, i;
  unsigned char tmp;

  if (devc->speed == devc->prev_speed)
    return;
  devc->prev_speed = devc->speed;

  revo71_mute (devc, 1);

  /* Pulse the PRST# signal to reset converters */
  OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x05) | 0x80,
	devc->mt_base + 0x05);
  oss_udelay (5000);
  OUTB (devc->osdev, INB (devc->osdev, devc->mt_base + 0x05) & ~0x80,
	devc->mt_base + 0x05);
  oss_udelay (5000);

  tmp = 0x03;
  if (rate <= 48000)
    tmp |= 0x00;
  else
    {
      if (rate <= 96000)
	tmp |= 0x04;
      else
	tmp |= 0x08;
    }

  /* Front DAC */

  writedac1 (devc, 0, 0x0c);
  writedac1 (devc, 1, tmp);
  writedac1 (devc, 2, 0x00);
  writedac1 (devc, 3, devc->dac1val[3]);
  writedac1 (devc, 4, devc->dac1val[4]);
  writedac1 (devc, 0, 0x0f);

  /* Surround DAC */
  writedac2 (devc, 1, 0x02);
  writedac2 (devc, 0, 0x06);

  tmp = 0x0e;

  if (devc->speed > 60000)
    {
      if (devc->speed > 120000)
	tmp |= 0x20;
      else
	tmp |= 0x10;
    }
  writedac2 (devc, 2, tmp);
  writedac2 (devc, 3, 0x01);

  for (i = 4; i < 10; i++)
    writedac2 (devc, i, devc->dac2val[i]);

  writedac2 (devc, 0xa, 0x00);
  writedac2 (devc, 1, 0x03);

  revo71_mute (devc, 0);
}

static int
revo71_set_akm (int dev, int ctrl, unsigned int cmd, int value)
{
  envy24ht_devc *devc = mixer_devs[dev]->hw_devc;

  if (cmd == SNDCTL_MIX_READ)
    {
      if (ctrl < 0 || ctrl > 4)
	return OSS_EIO;

      return devc->gains[ctrl];
    }

  if (cmd == SNDCTL_MIX_WRITE)
    {
      int left, right;

      left = value & 0xff;
      right = (value >> 8) & 0xff;

      switch (ctrl)
	{
	case 0:		/* Front */
	  writedac1 (devc, 0x03, left);
	  writedac1 (devc, 0x04, right);
	  break;

	case 1:		/* Rear */
	  writedac2 (devc, 0x06, left);
	  writedac2 (devc, 0x07, right);
	  break;

	case 2:		/* Center */
	  writedac2 (devc, 0x04, left);
	  right = left;
	  break;

	case 3:		/* LFE */
	  writedac2 (devc, 0x05, left);
	  right = left;
	  break;

	case 4:		/* Surround */
	  writedac2 (devc, 0x08, left);
	  writedac2 (devc, 0x09, right);
	  break;

	default:
	  return OSS_EINVAL;
	}

      value = left | (right << 8);
      return devc->gains[ctrl] = value;
    }

  return OSS_EINVAL;
}

static int
revo71_mixer_init (envy24ht_devc * devc, int dev, int group)
{
  int i, err;

  for (i = 0; i < 6; i++)
    devc->gains[i] = 0xffff;

  if ((group = mixer_ext_create_group (dev, 0, "ENVY24HT_GAIN")) < 0)
    return group;

  if ((err = mixer_ext_create_control (dev, group,
				       0, revo71_set_akm,
				       MIXT_STEREOSLIDER,
				       "GAIN_FRONT", 255,
				       MIXF_READABLE | MIXF_WRITEABLE)) < 0)
    return err;

  if ((err = mixer_ext_create_control (dev, group,
				       1, revo71_set_akm,
				       MIXT_STEREOSLIDER,
				       "GAIN_REAR", 255,
				       MIXF_READABLE | MIXF_WRITEABLE)) < 0)
    return err;

  if ((err = mixer_ext_create_control (dev, group,
				       2, revo71_set_akm,
				       MIXT_MONOSLIDER,
				       "GAIN_CENTER", 255,
				       MIXF_READABLE | MIXF_WRITEABLE)) < 0)
    return err;

  if ((err = mixer_ext_create_control (dev, group,
				       3, revo71_set_akm,
				       MIXT_MONOSLIDER,
				       "GAIN_LFE", 255,
				       MIXF_READABLE | MIXF_WRITEABLE)) < 0)
    return err;

  if ((err = mixer_ext_create_control (dev, group,
				       4, revo71_set_akm,
				       MIXT_STEREOSLIDER,
				       "GAIN_surround", 255,
				       MIXF_READABLE | MIXF_WRITEABLE)) < 0)
    return err;

  return 0;
}

envy24ht_auxdrv_t envy24ht_revo71_auxdrv = {
  revo71_card_init,
  revo71_mixer_init,
  revo71_set_rate,
  NULL,
  NULL,
  NULL,				/* revo71_private1 */
};

Copyright (C) 4Front Technologies, 2007. All rights reserved.

Back to index OSS web site


Copyright (C) 4Front Technologies, 2007. All rights reserved.
Back to index OSS web site