📄 dsc.c
字号:
/* Copyright 1997, ESS Technology, Inc. */
/* SCCSID @(#)dsc.c 1.120 11/18/98 */
/*
* This is to be shared with GAME
*/
#include "common.h"
#include "constvar.h"
#include "dsc.h"
#include "ioport.h"
#include "ir.h"
#include "sysinfo.h"
#include "util.h"
#include "config.h"
#ifdef ECHO
#include "echo.h"
#endif
#ifdef C80
#include "play.h"
#endif
#ifdef DSC
/*
* New 3881/3883 special AUX pin assignments:
* EAUX6: VFD data out. Serial port 1 data out (better not to use)
* EAUX7: VFD data in. Serial port 1 data in (better not to use)
* EAUX8: VFD clock output. Serial port 1 clock out (better not to use)
* EAUX9: SQSO (SQDT). Serial port 2 data in.
* EAUX10: SQCK. Serial port 2 clock out.
* EAUX11: IRQ out. Interrupt output to 3210/3220.
* EAUX12: C2PO. Interrupt input from CDROM (optional).
* EAUX13: 16550. Interrupt input from 16550 (optional).
* EAUX14: S0S1. Interrupt input from subQ code (optional).
* EAUX15: IR. Interrupt input from remote control.
*/
/************************************************************************
* Local defines. *
************************************************************************/
#ifndef DSC_SELECT /* We'll get rid of this via config.h */
#ifdef DVD_VCD
#define DSC_SELECT SET_AUX0
#define DSC_DESELECT CLEAR_AUX0
#else
#define DSC_SELECT SET_AUX5
#define DSC_DESELECT CLEAR_AUX5
#endif
#endif
/************************************************************************
* Following defines are valid for 3207VA or later chips. *
************************************************************************/
#ifdef DSC_DITHER
#define AUDIORCV1_DITHER 0x4 /* This is no good. Don't use it*/
#else
#define AUDIORCV1_DITHER 0
#endif
#ifdef DSC_SW_DETECT_CENTER
#define AUDIOADC2_RESET 0x40 /* Old style */
#else
#define AUDIOADC2_RESET 0 /* Don't ever reset, it *
* affacts ref. voltage.*/
#endif
/************************************************************************
* Following defines are valid for 3881 or later chips. *
************************************************************************/
#ifdef DSC_IRQ
#define DSC_CCHIP_CTL_IR_EN 0x40
#else
#define DSC_CCHIP_CTL_IR_EN 0
#endif
/************************************************************************
* Private functions. *
************************************************************************/
PRIVATE void DSC_init_irq_ctl(int, int, int, int, int);
/************************************************************************
* Variables used in this module only. *
************************************************************************/
#ifdef CUST6
unsigned int shadow_eaux0_dat; /* Shadow for dsc_aux0_dat */
unsigned int shadow_eaux1_dat; /* Shadow for dsc_aux1_dat */
#else
PRIVATE unsigned int shadow_eaux0_dat; /* Shadow for dsc_aux0_dat */
PRIVATE unsigned int shadow_eaux1_dat; /* Shadow for dsc_aux1_dat */
#endif
PRIVATE unsigned int shadow_eaux0_ctl; /* Shadow for dsc_aux0_ctl */
PRIVATE unsigned int shadow_eaux1_ctl; /* Shadow for dsc_aux1_ctl */
#ifdef DSC_IRQ
PRIVATE unsigned int shadow_irq_ctl; /* Shadow for dsc_irq_ctl */
PRIVATE unsigned int shadow_aux_mode; /* Shadow for dsc_aux_mode */
#endif
#ifdef SVIDEO_SELECT
unsigned char svideo_setting;
#endif
PRIVATE unsigned int shadow_audioxmt1; /* Shadow of audioxmt1 */
PRIVATE unsigned int shadow_cchip_ctl; /* Shadow of dsc_cchip_ctl*/
/*
* This routine has to be called before all DSC routine.
*
* This routine will set DSC select. Then it will only be toggled in
* timer interrupt.
*/
void DSC_getstatus()
{
int tmp, tmp1;
DSC_toggle();
#ifdef CLKDIV
if (((shadow_cchip_ctl = DSC_cmd(dsc_cchip_ctlm, 0)) >> 4) & 1) {
/* Warm boot */
if ((tmp = DSC_cmd(dsc_clkctlm, 0)) & 1)
{
/* Already running at full speed */
DSC_status = DSC_STATUS_RUNNING;
} else {
DSC_status = DSC_STATUS_STANDBY;
#ifdef IR
/* Read the code into cache so we can run at lower speed! */
#ifdef DSC_IRQ
IR_recv_interrupt_service(0);
#else
IR_recv_interrupt_service();
#endif
#endif
/* Running at 1/8th of full speed */
mvd[riface_width] = 0x81;
asm("nop");
asm("nop");
mvd[riface_wait_state] = 0x1f801f;
}
#ifdef IR_PHILIPS
IR_ctlbit = (tmp >> 1) & 1; /* Get the last control bit */
#endif
} else {
#ifdef IGNORE_POWERDONW
DSC_status = DSC_STATUS_RUNNING;
#else
DSC_status = DSC_STATUS_ACON;
#endif
#ifdef IR_PHILIPS
IR_ctlbit = 2; /* I.e. Any control bit will do. This is the *
* best setting if someone wants ACON to be ON */
#endif
}
#else
/* The old style using 3207's DCLK for power down */
#ifdef IGNORE_POWERDOWN
DSC_status = DSC_STATUS_RUNNING;
#else
tmp = (DSC_cmd(dsc_cchip_ctlm, 0) >> 3) & 2;
DSC_status = (DSC_cmd(dsc_clkctlm, 0) >> 5) & 1;
DSC_status |= tmp;
#endif
#endif
/* Check DSC_version */
tmp = DSC_cmd(dsc_audioapllmm, 0) & 0xff;
tmp1 = DSC_cmd(dsc_audioapllnm, 0) & 0xff;
DSC_version = 0; /* Pre 3207VA */
if ((tmp == 0x7d) && (tmp1 == 0x31))
DSC_version = 1; /* 3207 VA and later */
}
/*
* Toggle DSC_S (a convention to tell 3207 that 3210 is still alive, so
* it will not be reset accidentally.)
*
* We can't toggle DSC_S in the middle of communication, and this
* routine is called mostly inside timer interrupt handler. Originally,
* we have a semaphore to prevent calling this while communicating
* with 3207. The new mechanism will disable any interrupt while
* communicating with 3207, so semaphore is no longer needed.
*/
void DSC_toggle()
{
DSC_DESELECT;
DSC_SELECT;
}
/*
* Send DSC command from 3208/3210 to 3207
* dcs_c: CS1
* dsc_s: AUX3
* d[7:0]: data[7:0]
* DSC data space is at address 0x14000003 (i.e. assert CS1)
*/
unsigned int DSC_cmd(addr, data)
unsigned int addr;
unsigned int data;
{
volatile unsigned char* prt;
/*
* Disable interrupt while communicating with 3207 such address
* and data can always be in pair.
*/
mvd[riface_irqsuppress] = 0;
asm("nop");
prt = (char *) x14000003;
/* asserting dsc strobe from 3210 */
*prt = addr;
asm("nop"); asm("nop");
if (!(addr & 0x1)) {
*prt = data;
data = 0;
} else data = *prt;
return(data);
}
/*
* Reset 3207 to make sure left/right channel is not swapped.
*/
void DSC_reset_audio()
{
/* Reset 3207 so it will start from the left channel */
shadow_cchip_ctl &= ~2; /* Disable 07 audio DAC */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
DSC_cmd(dsc_audiorcv1, 0x80 | AUDIORCV1_DITHER);
/* Reset 07 audio recv */
DSC_cmd(dsc_audiorcv1, 0x90 | AUDIORCV1_DITHER);
/* Enable 07 audio recv */
shadow_cchip_ctl |= 2; /* Enable 07 audio DAC */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
#ifdef ES3207A
shadow_cchip_ctl &= ~0x20; /* Turn off mute */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
#endif
}
#ifdef ECHO
void DSC_mic_on(void)
{
int i;
unsigned int adc2;
volatile unsigned int *ptrdelay = (unsigned int *) x1c060000;
adc2 = DSC_version ? 0x20 : 0x24; /* 6dB gain for 3207 not 3881 */
if (ECHO_analog_bypass) {
adc2 |= 0x8; /* Add MIC input to speaker out */
/*
* Why doing analog by-pass, it is possible that there is no
* data from 3880 (e.g. MIC on but no echo and no CD data). In
* which case, if we have zero_mute, then there won't be any audible
* output!
*/
shadow_audioxmt1 &= 0xbf; /* Disable zero_mute */
DSC_cmd(dsc_audioxmt1, shadow_audioxmt1);
}
DSC_cmd(dsc_audioadc1, 0x08);
shadow_cchip_ctl |= 0x4; /* Enable MIC ports */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
/* Delay some time so cap. can be charged up. */
for (i = 0; i < 20; i++) (void) *ptrdelay;
DSC_cmd(dsc_audioadc2, 0x00 | AUDIOADC2_RESET);
/* cause soft reset adc */
DSC_cmd(dsc_audioadc2, adc2);
}
void DSC_mic_off(void)
{
shadow_cchip_ctl &= ~4; /* Disable MIC ports */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
DSC_cmd(dsc_audioadc2, 0x00 | AUDIOADC2_RESET);
/* cause soft reset adc */
shadow_audioxmt1 |= 0x40; /* Enable zero_mute (better S/N)*/
DSC_cmd(dsc_audioxmt1, shadow_audioxmt1);
}
#endif /* end of #ifdef ECHO */
/*
* Fuction to set and/or clear AUX pins on 3205/3207/3209.
*
* Inputs:
* sel: 0 - for dsc_aux0
* 1 - for dsc_aux1
* set: 0 - clear according to mask
* 1 - set according to mask
* 2 - tristate pads specified by mask
* mask: mask to be used
*/
void DSC_set_aux(sel, set, mask)
int sel, set, mask;
{
register psw_shadow, temp;
volatile char *ptr;
int data, ctl, *pdat, *pctl;
asm volatile("movfrs psw,%0": "=r" (psw_shadow) );
/* Non-cachable bank1 address (CS1) */
ptr = (char *) x14000003;
/* Decide which 3207 register to use (dsc_aux0 vs. dsc_aux1) */
if (sel) {
pdat = &shadow_eaux1_dat;
pctl = &shadow_eaux1_ctl;
data = dsc_aux1_data;
ctl = dsc_aux1_ctl;
} else {
pdat = &shadow_eaux0_dat;
pctl = &shadow_eaux0_ctl;
data = dsc_aux0_data;
ctl = dsc_aux0_ctl;
}
/* Disable interrupt so everything can happen together */
temp = 0x1fd5;
asm volatile("movtos %0,psw" : :"r" (temp));
asm("nop");
asm("nop");
/* Set the PAD value first (keep a copy in shadow) */
*ptr = data;
/* When setting or tri-stating, OR in the mask */
if (set) *ptr = (*pdat |= mask);
else *ptr = (*pdat &= ~mask);
/* Set the enable bit (unless it is tri-state) */
asm("nop");
*ptr = ctl;
/* When tri-stating, turn the bit off */
if (set == 2) *ptr = (*pctl &= ~mask);
else *ptr = (*pctl |= mask);
/* Restore PSD */
asm volatile("movtos %0,psw" : :"r" (psw_shadow));
}
/*
* Set 3207 TV mode to PAL or NTSC.
*
* Input:
* mode: TV_NTSC for NTSC
* TV_PAL for PAL
*/
void DSC_set_TV(mode)
int mode;
{
shadow_cchip_ctl &= ~1; /* Disable DVE */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
DSC_cmd(dsc_dvectl1, (mode == TV_NTSC) ? 0x06 : 0x04);
shadow_cchip_ctl |= 1; /* Enable DVE */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
}
#if (SVIDEO && !CUST3)
/*
* Turn s-video on or off.
*
* Input:
* on: 1: turn it on
* 0: turn it off
*/
void DSC_s_video(on)
int on;
{
int dvectl3;
dvectl3 = DSC_cmd(dsc_dvectl3m, 0); /* Get the current DVECTL3 */
if (on) dvectl3 &= ~6; /* Turn on S-Video */
else dvectl3 |= 6; /* Turn off S-Video */
shadow_cchip_ctl &= ~1; /* Disable DVE */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
DSC_cmd(dsc_dvectl3, dvectl3);
shadow_cchip_ctl |= 1; /* Enable DVE */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
}
#endif
/*
* This routine is called to power down 3210. When 3210 is in power
* down mode, it may run at 27MHz from 3207/9 (the old way) or run
* from internal clock divider (newer chips.)
*
* This routine will ask 3207/9 to reset 3210; therefore, it will never
* return.
*/
#if (ES3207A || (CUST71 && C80))
void DSC_mute_on() {
volatile unsigned int *ptr = (unsigned int *) x1c060000;
int i, foo;
shadow_cchip_ctl |= 0x20;
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
for (i=0; i<60000; i++) /* wait for pin VREFM turn high */
foo = *ptr; /* wait 360 ns; total wait 20ms */
}
#if (CUST71 && C80)
void DSC_mute_off() {
volatile unsigned int *ptr = (unsigned int *) x1c060000;
int i, foo;
shadow_cchip_ctl &= 0xdf;
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
for (i=0; i<60000; i++) /* wait for pin VREFM turn high */
foo = *ptr; /* wait 360 ns; total wait 20ms */
}
#endif
#endif
#ifndef PLAYONLY
#if (!CUST71 || POWER_ON)
void DSC_powerdown()
{
int clkctl = 0x70; /* PLL, PCLK2X, divider 0, boot */
mvd[riface_irqmask] = 0; /* Disable all interrupts */
#ifdef ES3207A
DSC_mute_on();
#endif
shadow_cchip_ctl &= ~1; /* Disable DVE */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
DSC_cmd(dsc_dvectl3, 0x0); /* Power down video */
#ifdef CLKDIV
shadow_cchip_ctl = 0x38; /* Audio mute, warm boot, power *
* saving, disable MIC/audio */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
#ifdef IR_PHILIPS
clkctl |= ((IR_ctlbit & 1) << 1); /* Record the last control bit. *
* DON'T change b2, 3881 can't *
* take it!! */
#endif
DSC_cmd(dsc_clkctl, clkctl);
#else
shadow_cchip_ctl = 0x28; /* Audio mute, cold boot, power *
* saving, disable MIC/audio */
DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -