dsc.c
来自「ESS3890+SL原代码(1*16内存)」· C语言 代码 · 共 1,030 行 · 第 1/2 页
C
1,030 行
/* Copyright 1997, ESS Technology, Inc. *//* SCCSID @(#)dsc.c 4.16.1.4 01/18/05 *//* * This is to be shared with GAME */#include "vcxi.h"#include "ir.h"#include "util.h"#ifdef ECHO#include "echo.h"#endif#include "low.h"#include "const.h"#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. * (for ES3890 only below) * EAUX16: Gamepad CLK * EAUX17: Gamepad LATCH * EAUX18: Gamepad2 DATA *//************************************************************************ * Local defines. * ************************************************************************/#ifdef NO_ZERO_MUTE#define ZERO_MUTE_BIT 0x00#else#define ZERO_MUTE_BIT 0x40#endif#ifdef IO3890/* video DACs power-down bit is inverted on ES3890 *//* * DSC_VIDEO_ON is most likely OK for S-video as well because C input of TV * usually has a filter to get chroma signal. */#define DSC_VIDEO_ON DSC_cmd(dsc_dvectl3, 0x0) /* Y+V */#define DSC_VIDEO_OFF DSC_cmd(dsc_dvectl3, 0x1) /* All off */#define DSC_COMPOSITE_ONLY DSC_cmd(dsc_dvectl3, 0x2) /* V only */#else#define DSC_VIDEO_ON DSC_cmd(dsc_dvectl3, 0x1) /* Y+C+V */#define DSC_VIDEO_OFF DSC_cmd(dsc_dvectl3, 0x0) /* All off */#define DSC_COMPOSITE_ONLY DSC_cmd(dsc_dvectl3, 0x7) /* V only */#endif /* IO3890 *//************************************************************************ * 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 * * affects 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. * ************************************************************************/PRIVATE unsigned int shadow_eaux0_dat; /* Shadow for dsc_aux0_dat */PRIVATE unsigned int shadow_eaux1_dat; /* Shadow for dsc_aux1_dat */PRIVATE unsigned int shadow_eaux0_ctl; /* Shadow for dsc_aux0_ctl */PRIVATE unsigned int shadow_eaux1_ctl; /* Shadow for dsc_aux1_ctl */#ifdef IO3890PRIVATE unsigned int shadow_eaux2_dat; /* Shadow for dsc_aux2_dat */PRIVATE unsigned int shadow_eaux2_ctl; /* Shadow for dsc_aux2_ctl */#endif#ifdef DSC_IRQPRIVATE unsigned int shadow_irq_ctl; /* Shadow for dsc_irq_ctl */PRIVATE unsigned int shadow_aux_mode; /* Shadow for dsc_aux_mode */#endif#ifdef SVIDEO_SELECTunsigned char svideo_setting;#endifPRIVATE 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(); 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"); /* B0,B3: 0 WS and B1,B2: 32 WS */ mvd[riface_wait_state] = 0x1f801f; }#ifdef IR_PHILIPS IR_ctlbit = (tmp >> 1) & 1; /* Get the last control bit */#endif } else {#ifdef IGNORE_POWERDOWN 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 }}/* * 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; volatile unsigned int *ptrdelay = (unsigned int *) bank3safe; /* * Disable interrupt while communicating with 3207 such address * and data can always be in pair. */ mvd[riface_irqsuppress] = 0; asm("nop"); prt = DSC_ADDRESS; /* asserting dsc strobe from 3210 */ *prt = addr; (void) *ptrdelay; 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(){#ifdef IO3890 /* no internal audio DAC */ /* Need to set these two registers to improve SNR */ DSC_cmd(dsc_audiorcv1, 0xc0); DSC_cmd(dsc_audiorcv2, 0x08);#else#ifdef ES3207A int i; volatile unsigned int *ptrdelay = (unsigned int *) bank3safe;#endif /* 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 for (i = 0; i < 10000; i++) (void) *ptrdelay; shadow_cchip_ctl &= ~0x20; /* Turn off mute */ DSC_cmd(dsc_cchip_ctl, shadow_cchip_ctl);#endif#endif /* IO3890 */}#ifdef ECHOvoid DSC_mic_on(void){ int i; unsigned int adc2; volatile unsigned int *ptrdelay = (unsigned int *) bank3safe;#ifdef MIC_RECORD adc2 = 0x24; /* Add 6dB gain for even 3883 for mic record */#else adc2 = 0x20; /* NO 6dB gain */#endif#ifndef IO3890 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! */#ifndef NO_ZERO_MUTE shadow_audioxmt1 &= 0xbf; /* Disable zero_mute */ DSC_cmd(dsc_audioxmt1, shadow_audioxmt1);#endif } DSC_cmd(dsc_audioadc1, 0x08);#else#if (!defined(DSC_AUDIOCLK) && !defined(AUDIOCLK) && defined(FS384)) DSC_cmd(dsc_audioadc1, 0x0c);#else DSC_cmd(dsc_audioadc1, 0x0b);#endif#endif /* IO3890 */ 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 */#ifndef NO_ZERO_MUTE shadow_audioxmt1 |= 0x40; /* Enable zero_mute (better S/N)*/ DSC_cmd(dsc_audioxmt1, shadow_audioxmt1);#endif}#endif /* end of #ifdef ECHO */void DSC_zero_mute(int on){#ifdef ECHO if (vcx_echo == -1) #endif { if (on) { shadow_audioxmt1 |= 0x40; } else { shadow_audioxmt1 &= 0xbf; } DSC_cmd(dsc_audioxmt1, shadow_audioxmt1); }}/* * Fuction to set and/or clear AUX pins on 3205/3207/3209. * * Inputs: * sel: 0 - for dsc_aux0 * 1 - for dsc_aux1 * 2 - for dsc_aux2 * 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; volatile unsigned int *ptrdelay = (unsigned int *) bank3safe; asm volatile("movfrs psw,%0": "=r" (psw_shadow) ); /* Non-cachable bank1 address (CS1) */ ptr = DSC_ADDRESS; /* Decide which 3207 register to use (dsc_aux0 vs. dsc_aux1) */#ifdef IO3890 if (sel == 2) { pdat = &shadow_eaux2_dat; pctl = &shadow_eaux2_ctl; data = dsc_aux2_data; ctl = dsc_aux2_ctl; } else #endif if (sel == 1) { 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; (void) *ptrdelay; /* 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) */ (void) *ptrdelay; *ptr = ctl; (void) *ptrdelay; /* 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);}#ifdef SVIDEO/* * 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 */#ifdef IO3890 dvectl3 |= 0x80; /* Enable Y and chroma output */#endif } else {#ifdef IO3890 dvectl3 |= 2; /* Turn off Y DAC of S-video */ dvectl3 &= ~0x80; /* Make C DAC outputs V signal */#else dvectl3 |= 6; /* Turn off S-Video */#endif } 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. */#ifdef ES3207Avoid DSC_mute_on() { volatile unsigned int *ptr = (unsigned int *) bank3safe; 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 0void DSC_mute_off() { volatile unsigned int *ptr = (unsigned int *) bank3safe; 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#ifdef PLAY20void 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_VIDEO_OFF; /* Power down video */ 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); while (1);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?