/***************************************************************************
*       NAME:  LOADDAC.C $Revision: 1.9 $
**      COPYRIGHT:
**      "Copyright (c) 1994,1995 by e-Tek Labs"
**
**       "This software is furnished under a license and may be used,
**       copied, or disclosed only in accordance with the terms of such
**       license and with the inclusion of the above copyright notice.
**       This software or any other copies thereof may not be provided or
**       otherwise made available to any other person. No title to and
**       ownership of the software is hereby transfered."
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>

#include "sbosdefs.h"
#include "sbosdata.h"
#include "shared.h"
#include "dac.h"

unsigned int codec_addr;
unsigned int codec_data;
unsigned int codec_status;
unsigned int codec_pio;

extern SHARED far * shared;
extern BOARD_CFG far * config;

/****************************************************************************

FUNCTION DEFINITION:
Probe_Codec -

DESCRIPTION:

EXPECTS:

MODIFIES:

SEE ALSO:

RETURNS:

*/
int Probe_Codec(BOARD_CFG *config,int port)
{
unsigned char setup;
unsigned char bits;
unsigned char version;
unsigned int enable_16;
int temp;

codec_addr = port+CODEC_ADDR;
codec_data = port+CODEC_DATA;
codec_status = port+CODEC_STATUS;
codec_pio = port+CODEC_PIO;

setup = 0x00;		/* default codec to disabled */
enable_16 = FALSE;
if (port >= 0x300 && port <= 0x3f0)
	{
	enable_16 = TRUE;
	bits = (port - 0x30C) >> 4;		/* isolate bits */
	setup |= bits;
	}
if (enable_16)
	setup |= 0x40;

// This is not needed if 16 bit channels are not allowed. (not for SB)
#ifdef NEVER
if (config->rec_dma >= 4)
	setup |= 0x10;					/* record is 16 bit channel */
if (config->play_dma >= 4)
	setup |= 0x20;					/* play is 16 bit channel */
#endif

outp(config->upper_base_port+0x06,setup);		/* program the interface */

/* clear any pending IRQs */
(void)inp(codec_status);
outp(codec_status,0);

for (temp=0;temp<1000;temp++)
	{
	if (inp(codec_addr) & CODEC_INIT)
		;
	else
		{
		disable();
		outp(codec_addr,MISC_INFO);
		outp(codec_data,0x40);		// Force to mode 2
		version = inp(codec_data) & 0x0f;
		enable();
		if ((version >= 1) && (version < 15))
			{
// DMA channels are not combined on a MAX ....
			disable();
			outp(codec_addr,CODEC_MCE|IFACE_CTRL);
			outp(codec_data,0x08);		// ACAL only
			outp(codec_addr,IFACE_CTRL);
			enable();
			return(1);
			}
		}
	}
return(0);
}

/****************************************************************************

FUNCTION DEFINITION:
init_codec -

DESCRIPTION:

EXPECTS:

MODIFIES:

SEE ALSO:

RETURNS:

*/
void init_codec(unsigned int adlib_only)
{
unsigned char val;

if (!Probe_Codec(config,config->codec_base_port))
	{
	// Can't find CODEC where its supposed to be ....
	shared->status &= ~STAT_CODEC_ENABLED;
	}
else
	{
	// OK we got it. Set up data structs ....
	shared->status |= STAT_CODEC_ENABLED;
	shared->codec_base = config->codec_base_port;

// Only init the paths that we care about
	disable();

	outp(codec_addr,SYN_LEFT_INPUT);
	outp(codec_data,0x80);
	outp(codec_addr,SYN_RIGHT_INPUT);
	outp(codec_data,0x80);

	outp(codec_addr,LEFT_OUTPUT);
	outp(codec_data,0x80);
	outp(codec_addr,RIGHT_OUTPUT);
	outp(codec_data,0x80);

	outp(codec_addr,LEFT_LINE_IN);
	outp(codec_data,0x80);
	outp(codec_addr,RIGHT_LINE_IN);
	outp(codec_data,0x80);

	outp(codec_addr,MISC_INFO);
	outp(codec_data,0x6C);

	outp(codec_addr,ALT_FEATURE_2);
#ifdef VAR_PCM
	outp(codec_data,0xC6); // Enable play fifo irqs, var PCM, synth->aux 1
//	outp(codec_data,0xE6); // Enable play fifo irqs, var PCM, synth->aux 1
	outp(codec_addr,CODEC_MCE|PLAYBK_FORMAT);
	outp(codec_data,0x01);	// select 16.9M clock ....
	outp(codec_addr,PLAYBK_FORMAT);
#else
	outp(codec_data,0xC2); // Disable play fifo irqs, no var PCM, synth->aux 1
//	outp(codec_data,0xE2); // Disable play fifo irqs, no var PCM, synth->aux 1
#endif

#ifdef NEVER
	outp(codec_addr,MONO_IO_CTRL);
	outp(codec_data,0xC0);
#endif

	enable();
	if (adlib_only)
		enable_outputs();
	}
	
if(adlib_only)
	shared->status &= ~STAT_CODEC_ENABLED;
}

/****************************************************************************

FUNCTION DEFINITION:
enable_outputs -

DESCRIPTION:

EXPECTS:

MODIFIES:

SEE ALSO:

RETURNS:

*/
void enable_outputs(void)
{
if (shared->status & STAT_CODEC_ENABLED)
	{
// Only init the paths that we care about
	disable();

	outp(codec_addr,SYN_LEFT_INPUT);
	outp(codec_data,0x08);		// 0db gain
	outp(codec_addr,SYN_RIGHT_INPUT);
	outp(codec_data,0x08);		// 0db gain

	outp(codec_addr,LEFT_OUTPUT);
	outp(codec_data,shared->dac_atten); // DAC master volume control 
	outp(codec_addr,RIGHT_OUTPUT);
	outp(codec_data,shared->dac_atten);	// DAC master volume control 

#ifdef NEVER
	if (shared->status & STAT_LINE_ENABLED)
		{
		outp(codec_addr,LEFT_LINE_IN);
		outp(codec_data,0x08);		// 0db gain
		outp(codec_addr,RIGHT_LINE_IN);
		outp(codec_data,0x08);		// 0db gain
		}
#endif

	enable();
	}
}
