727 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			727 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
#ifdef HAVE_XORG_CONFIG_H
 | 
						|
#include <xorg-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
#include "xf86.h"
 | 
						|
#include "xf86i2c.h"
 | 
						|
#include "msp3430.h"
 | 
						|
#include "i2c_def.h"
 | 
						|
 | 
						|
#define CONTROL         0x00
 | 
						|
#define WR_DEM          0x10
 | 
						|
#define RD_DEM          0x11
 | 
						|
#define WR_DSP          0x12
 | 
						|
#define RD_DSP          0x13
 | 
						|
 | 
						|
 | 
						|
void InitMSP34xxG(MSP3430Ptr m);
 | 
						|
void InitMSP34x5D(MSP3430Ptr m);
 | 
						|
void CheckModeMSP34x5D(MSP3430Ptr m);
 | 
						|
char *MSP_getProductName (CARD16 product_id);
 | 
						|
void mpause(int milliseconds);
 | 
						|
 | 
						|
#define __MSPDEBUG__	0
 | 
						|
 | 
						|
#if __MSPDEBUG__ > 3
 | 
						|
 | 
						|
void MSPBeep(MSP3430Ptr m, CARD8 freq);
 | 
						|
#define __MSPBEEP MSPBeep(m,0x14);
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
#define __MSPBEEP 
 | 
						|
#endif
 | 
						|
 | 
						|
static void SetMSP3430Control(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegValueHigh, CARD8 RegValueLow)
 | 
						|
{
 | 
						|
   I2CByte data[3];
 | 
						|
   
 | 
						|
   data[0]=RegAddress;
 | 
						|
   data[1]=RegValueHigh;
 | 
						|
   data[2]=RegValueLow;
 | 
						|
   
 | 
						|
   I2C_WriteRead(&(m->d),data,3,NULL,0);
 | 
						|
}
 | 
						|
 | 
						|
static void SetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow, 
 | 
						|
     CARD8 RegValueHigh, CARD8 RegValueLow)
 | 
						|
{
 | 
						|
   I2CByte data[5];
 | 
						|
#ifdef MSP_DEBUG
 | 
						|
   if(!m->registers_present[RegSubAddressLow]){
 | 
						|
   	xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_ERROR, "Attempt to access non-existent register in MSP34xxX: 0x%02x 0x%02x 0x%02x <- 0x%02x 0x%02x\n",
 | 
						|
		RegAddress, RegSubAddressHigh, RegSubAddressLow, RegValueHigh, RegValueLow);
 | 
						|
   	}
 | 
						|
#endif
 | 
						|
   
 | 
						|
   data[0] = RegAddress;
 | 
						|
   data[1] = RegSubAddressHigh;
 | 
						|
   data[2] = RegSubAddressLow;
 | 
						|
   data[3] = RegValueHigh;
 | 
						|
   data[4] = RegValueLow;
 | 
						|
   
 | 
						|
   I2C_WriteRead(&(m->d),data,5,NULL,0);
 | 
						|
}
 | 
						|
 | 
						|
static void GetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow,
 | 
						|
            CARD8 *RegValueHigh, CARD8 *RegValueLow)
 | 
						|
{
 | 
						|
   I2CByte  send[3];
 | 
						|
   I2CByte  receive[2];
 | 
						|
   
 | 
						|
   send[0] = RegAddress;
 | 
						|
   send[1] = RegSubAddressHigh;
 | 
						|
   send[2] = RegSubAddressLow;
 | 
						|
   
 | 
						|
   I2C_WriteRead(&(m->d), send, 3, receive, 2);
 | 
						|
   
 | 
						|
   *RegValueHigh = receive[0];
 | 
						|
   *RegValueLow = receive[1];
 | 
						|
}
 | 
						|
 | 
						|
#if __MSPDEBUG__ > 2
 | 
						|
static void MSP3430DumpStatus(MSP3430Ptr m)
 | 
						|
{
 | 
						|
CARD8 status_hi, status_lo;
 | 
						|
CARD8 subaddr, data[2];
 | 
						|
 | 
						|
GetMSP3430Data(m, RD_DEM, 0x02, 0x00, &status_hi, &status_lo);
 | 
						|
xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: SAP(8)=%d mono/NICAM(7)=%d stereo=%d %s O_1=%d O_0=%d 2nd car=%d 1st car=%d\n",
 | 
						|
		status_hi & 1, (status_lo>>7) & 1, (status_lo>>6)&1, 
 | 
						|
		(status_lo>>5)? ( (status_hi>>1)&1? "bad NICAM reception" : "NICAM" ) : 
 | 
						|
		                ((status_hi>>1)&1 ? "bogus" : "ANALOG FM/AM") , 
 | 
						|
		(status_lo>>4)&1, (status_lo>>3)&1,!( (status_lo>>2)&1), !((status_lo>>1)&1));
 | 
						|
 | 
						|
GetMSP3430Data(m, RD_DEM, 0x00, 0x7E, &status_hi, &status_lo);
 | 
						|
xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: standard result=0x%02x%02x\n",
 | 
						|
		status_hi, status_lo);
 | 
						|
subaddr=0x0;
 | 
						|
I2C_WriteRead(&(m->d), &subaddr, 1, data, 2);
 | 
						|
xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: control=0x%02x%02x\n",
 | 
						|
		data[1], data[0]);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* wrapper */
 | 
						|
void InitMSP3430(MSP3430Ptr m)
 | 
						|
{
 | 
						|
  #if __MSPDEBUG__ > 1
 | 
						|
  xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP3430(m->connector=%d, m->standard=%d, m->chip_family=%d)\n",
 | 
						|
  		m->connector, m->standard, m->chip_family);
 | 
						|
  #endif
 | 
						|
	switch (m->chip_family) {
 | 
						|
		case MSPFAMILY_34x0G:
 | 
						|
			InitMSP34xxG(m);
 | 
						|
			break;
 | 
						|
		case MSPFAMILY_34x5G:
 | 
						|
			InitMSP34xxG(m);
 | 
						|
			break;
 | 
						|
		case MSPFAMILY_34x5D:
 | 
						|
			InitMSP34x5D(m);
 | 
						|
			break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*-----------------------------------------------------------------
 | 
						|
| common functions for all MSP34xx chips 
 | 
						|
|----------------------------------------------------------------*/
 | 
						|
 | 
						|
MSP3430Ptr DetectMSP3430(I2CBusPtr b, I2CSlaveAddr addr)
 | 
						|
{
 | 
						|
   MSP3430Ptr m;
 | 
						|
   I2CByte a;
 | 
						|
   CARD8 hardware_version, major_revision, product_code, rom_version;
 | 
						|
   Bool supported;
 | 
						|
   
 | 
						|
   m = calloc(1,sizeof(MSP3430Rec));
 | 
						|
   if(m == NULL)return NULL;
 | 
						|
   m->d.DevName = strdup("MSP34xx");
 | 
						|
   m->d.SlaveAddr = addr;
 | 
						|
   m->d.pI2CBus = b;
 | 
						|
   m->d.NextDev = NULL;
 | 
						|
   m->d.StartTimeout = b->StartTimeout;
 | 
						|
   m->d.BitTimeout = b->BitTimeout;
 | 
						|
   m->d.AcknTimeout = b->AcknTimeout;
 | 
						|
   m->d.ByteTimeout = b->ByteTimeout;
 | 
						|
   
 | 
						|
   if(!I2C_WriteRead(&(m->d), NULL, 0, &a, 1))
 | 
						|
   {
 | 
						|
       free(m->d.DevName);
 | 
						|
       free(m);
 | 
						|
	return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
	m->standard=MSP3430_NTSC;
 | 
						|
	m->connector=MSP3430_CONNECTOR_1;
 | 
						|
	m->mode=MSPMODE_STEREO_A;	/*stereo or chanel A if avail. */
 | 
						|
    	m->c_format=MSPFORMAT_UNKNOWN;
 | 
						|
    	m->c_standard=MSPSTANDARD_UNKNOWN;
 | 
						|
    	m->c_matrix=m->c_fmmatrix=m->c_source=0;
 | 
						|
	m->volume=0;
 | 
						|
	m->recheck=FALSE;
 | 
						|
 | 
						|
   GetMSP3430Data(m, RD_DSP, 0x00, 0x1E, &hardware_version, &major_revision);
 | 
						|
   GetMSP3430Data(m, RD_DSP, 0x00, 0x1F, &product_code, &rom_version);
 | 
						|
   m->hardware_version=hardware_version;
 | 
						|
   m->major_revision=major_revision;
 | 
						|
   m->product_code=product_code;
 | 
						|
   m->rom_version=rom_version;
 | 
						|
 | 
						|
   m->chip_id=((major_revision << 8) | product_code);
 | 
						|
   
 | 
						|
   supported=FALSE;
 | 
						|
   switch (major_revision) {
 | 
						|
   case 4:	/* 34xxD */
 | 
						|
      switch (product_code) {
 | 
						|
	  case 0x05: /* 3405D */
 | 
						|
	  case 0x0A: /* 3410D */
 | 
						|
	  case 0x0F: /* 3415D */
 | 
						|
	  	m->chip_family=MSPFAMILY_34x5D;
 | 
						|
		m->recheck=TRUE;
 | 
						|
		supported=TRUE;
 | 
						|
		break;
 | 
						|
      default:
 | 
						|
	  	m->chip_family=MSPFAMILY_34x0D;
 | 
						|
      }
 | 
						|
	  break;
 | 
						|
   case 7:	/* 34xxG */
 | 
						|
   	switch(product_code){
 | 
						|
		case 0x00:
 | 
						|
		case 0x0A:
 | 
						|
		case 0x1E:
 | 
						|
		case 0x28:
 | 
						|
		case 0x32:
 | 
						|
		  	m->chip_family=MSPFAMILY_34x0G;
 | 
						|
			supported=TRUE;
 | 
						|
			break;
 | 
						|
		case 0x0f:
 | 
						|
		case 0x19:
 | 
						|
		case 0x2d:
 | 
						|
		case 0x37:
 | 
						|
		case 0x41:
 | 
						|
		  	m->chip_family=MSPFAMILY_34x5G;
 | 
						|
			supported=TRUE;
 | 
						|
			#ifdef MSP_DEBUG
 | 
						|
			memset(m->registers_present, 0, 256);
 | 
						|
			#define A(num) m->registers_present[(num)]=1;
 | 
						|
			#define B(num1, num2) memset(&(m->registers_present[num1]), 1, num2-num1);
 | 
						|
			A(0x20)
 | 
						|
			A(0x30)
 | 
						|
			A(0x40)
 | 
						|
			A(0x00)
 | 
						|
			B(0x01, 0x08)
 | 
						|
			B(0x0B, 0x0E)
 | 
						|
			A(0x10)
 | 
						|
			B(0x12,0x14)
 | 
						|
			A(0x16)
 | 
						|
			A(0x29)
 | 
						|
			#undef B
 | 
						|
			#undef A
 | 
						|
			#endif
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
		  	m->chip_family=MSPFAMILY_UNKNOWN;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
   default:
 | 
						|
	  	m->chip_family=MSPFAMILY_UNKNOWN;
 | 
						|
   }
 | 
						|
   
 | 
						|
	xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Found %s%s, rom version 0x%02x, chip_id=0x%04x\n",
 | 
						|
		MSP_getProductName(m->chip_id), supported?"":" (unsupported)", rom_version, m->chip_id);
 | 
						|
 | 
						|
	if (!supported) {
 | 
						|
            free(m->d.DevName);
 | 
						|
            free(m);
 | 
						|
            return NULL;
 | 
						|
	}
 | 
						|
   if(!I2CDevInit(&(m->d)))
 | 
						|
   {
 | 
						|
       free(m->d.DevName);
 | 
						|
       free(m);
 | 
						|
       return NULL;
 | 
						|
   }
 | 
						|
 | 
						|
   return m;  
 | 
						|
}
 | 
						|
 | 
						|
void ResetMSP3430(MSP3430Ptr m)
 | 
						|
{
 | 
						|
    /* Reset the MSP3430 */
 | 
						|
    SetMSP3430Control(m, 0x00, 0x80, 0x00);
 | 
						|
    /* Set it back to normal operation */
 | 
						|
    SetMSP3430Control(m, 0x00, 0x00, 0x00);
 | 
						|
 | 
						|
    m->c_format=MSPFORMAT_UNKNOWN;
 | 
						|
    m->c_standard=MSPSTANDARD_UNKNOWN;
 | 
						|
    m->c_matrix=m->c_fmmatrix=m->c_source=0;
 | 
						|
	m->volume=0;
 | 
						|
}   
 | 
						|
 | 
						|
void MSP3430SetVolume (MSP3430Ptr m, CARD8 value)
 | 
						|
{
 | 
						|
    CARD8 result;
 | 
						|
#if 0
 | 
						|
    CARD8 old_volume;
 | 
						|
    GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result);   
 | 
						|
    xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 result 0x%02x\n", result);
 | 
						|
#endif
 | 
						|
    /* save an extra Get call */
 | 
						|
    result=0;
 | 
						|
 | 
						|
    SetMSP3430Data(m, WR_DSP, 0x00, 0x00, value, result);
 | 
						|
 | 
						|
    SetMSP3430Data(m, WR_DSP, 0x00, 0x07, value, 0);
 | 
						|
    m->volume=value;
 | 
						|
 | 
						|
#if __MSPDEBUG__ > 2
 | 
						|
    MSP3430DumpStatus(m); 
 | 
						|
    __MSPBEEP
 | 
						|
    GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result);
 | 
						|
    xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 volume 0x%02x\n",value);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void MSP3430SetSAP (MSP3430Ptr m, int mode)
 | 
						|
{
 | 
						|
	xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Put actual code to change SAP here\n");
 | 
						|
 | 
						|
      SetMSP3430Data(m, WR_DSP, 0x00, 0x08, mode & 0xff, 0x20); 
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#if 0
 | 
						|
void MSP3430SetSource(MSP3430Ptr m, CARD8 value)
 | 
						|
{
 | 
						|
    /* Write to DSP, register 0x0008, (loudspeaker channel source/matrix) */
 | 
						|
    /* This sets the source to the TV tuner, for stereo operation */
 | 
						|
    SetMSP3430Data(m, WR_DSP, 0x00, 0x08, value, 0x20);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
char *MSP_getProductName (CARD16 product_id)
 | 
						|
{
 | 
						|
	switch (product_id) {
 | 
						|
		case 0x0400: return "MSP3400D";
 | 
						|
		case 0x040a: return "MSP3410D";
 | 
						|
		case 0x0405: return "MSP3405D";
 | 
						|
		case 0x040f: return "MSP3415D";
 | 
						|
		case 0x0700: return "MSP3400G";
 | 
						|
		case 0x070a: return "MSP3410G";
 | 
						|
		case 0x071e: return "MSP3430G";
 | 
						|
		case 0x0728: return "MSP3440G";
 | 
						|
		case 0x0732: return "MSP3450G";
 | 
						|
		case 0x070f: return "MSP3415G";
 | 
						|
		case 0x0719: return "MSP3425G";
 | 
						|
		case 0x072d: return "MSP3445G";
 | 
						|
		case 0x0737: return "MSP3455G";
 | 
						|
		case 0x0741: return "MSP3465G";
 | 
						|
	}
 | 
						|
	return "MSP - unknown type";
 | 
						|
}
 | 
						|
 | 
						|
#if __MSPDEBUG__ > 2
 | 
						|
/*puts beep in MSP output
 | 
						|
    freq = 0x01 - 16Hz ... 0x40 - 1kHz ... 0xff - 4kHz  
 | 
						|
*/
 | 
						|
void MSPBeep(MSP3430Ptr m, CARD8 freq) {
 | 
						|
    SetMSP3430Data (m, WR_DSP, 0x00, freq, 0x7f, 0x40);
 | 
						|
    mpause(100);
 | 
						|
    SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x00);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
void mpause(int milliseconds) {
 | 
						|
    int i,m;
 | 
						|
    m=milliseconds/20;
 | 
						|
    for (i=0;i<m;i++) usleep(20000);
 | 
						|
}
 | 
						|
 | 
						|
/*-----------------------------------------------------------------
 | 
						|
| specific functions for all MSP34xxG chips 
 | 
						|
|----------------------------------------------------------------*/
 | 
						|
 | 
						|
void InitMSP34xxG(MSP3430Ptr m)
 | 
						|
{
 | 
						|
 | 
						|
  #if __MSPDEBUG__ > 1
 | 
						|
  xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP34xxG(m->connector=%d, m->standard=%d, m->chip_family=%d)\n",
 | 
						|
  		m->connector, m->standard, m->chip_family);
 | 
						|
  #endif
 | 
						|
   /* Reset MSP3430 */
 | 
						|
   SetMSP3430Control(m, 0x00, 0x80, 0x00);
 | 
						|
   /* Set it back to normal operation */
 | 
						|
   SetMSP3430Control(m, 0x00, 0x00, 0x00);
 | 
						|
   
 | 
						|
   /*set MODUS register */
 | 
						|
   /* bits: 0 - automatic sound detection */
 | 
						|
   /*       1 - enable STATUS change */
 | 
						|
   /*       12 - detect 6.5 Mhz carrier as D/K1, D/K2 or D/K NICAM  (does not seem to work ) */
 | 
						|
   /*       13 - detect 4.5 Mhz carrier as BTSC */ 
 | 
						|
   if ( (m->standard & 0xff) == MSP3430_PAL )
 | 
						|
   {
 | 
						|
      SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x30, 0x03|0x08);    /* make O_ pins tristate */
 | 
						|
      /* PAL standard */
 | 
						|
      SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x01); /* possibly wrong */
 | 
						|
   } else {
 | 
						|
      SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x20, 0x03|0x08);
 | 
						|
      /* standard selection is M-BTSC-Stereo */
 | 
						|
      SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x20); 
 | 
						|
   }
 | 
						|
   
 | 
						|
   switch(m->connector){
 | 
						|
         case MSP3430_CONNECTOR_1:
 | 
						|
	        SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x03, 0x20);
 | 
						|
	        break;
 | 
						|
	 case MSP3430_CONNECTOR_2:
 | 
						|
		/* this has not been checked yet.. could be bogus */
 | 
						|
    		/* SCART Input Prescale: 0 dB gain */
 | 
						|
		SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00);
 | 
						|
    		SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20);   	
 | 
						|
		break;
 | 
						|
	case MSP3430_CONNECTOR_3:
 | 
						|
	default:
 | 
						|
    		/* SCART Input Prescale: 0 dB gain */
 | 
						|
		SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00);
 | 
						|
		
 | 
						|
    		SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20);
 | 
						|
    		break;
 | 
						|
	}
 | 
						|
	      
 | 
						|
    switch(m->standard){
 | 
						|
        case MSP3430_PAL:
 | 
						|
     		SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03);
 | 
						|
     		SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a);
 | 
						|
                SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x03);
 | 
						|
                /* Set volume to FAST_MUTE. */
 | 
						|
     	        SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00);
 | 
						|
	        break;
 | 
						|
        case MSP3430_PAL_DK1:
 | 
						|
     		SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03);
 | 
						|
     		SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a);
 | 
						|
		SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x04);
 | 
						|
                /* Set volume to FAST_MUTE. */
 | 
						|
     	        SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00);
 | 
						|
		break;
 | 
						|
	case MSP3430_SECAM: /* is this right ? */
 | 
						|
        case MSP3430_NTSC:         
 | 
						|
                /* Write to DSP, register 0x000E, (prescale FM/FM matrix) */
 | 
						|
                SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03);
 | 
						|
 | 
						|
                /* Set volume to FAST_MUTE. */
 | 
						|
                SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00);
 | 
						|
		break;
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/*-----------------------------------------------------------------
 | 
						|
| specific functions for all MSP34x5D chips 
 | 
						|
|----------------------------------------------------------------*/
 | 
						|
 | 
						|
void InitMSP34x5D(MSP3430Ptr m)
 | 
						|
{
 | 
						|
int count;
 | 
						|
CARD8 high,low;
 | 
						|
CARD16 result,standard;
 | 
						|
CARD16 peak;
 | 
						|
 | 
						|
 | 
						|
if (m->c_format==MSPFORMAT_UNKNOWN) ResetMSP3430(m);
 | 
						|
else {
 | 
						|
    /*mute volume*/
 | 
						|
    SetMSP3430Data (m, WR_DSP, 0x00, 0x00, 0x00, 0x00);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    switch(m->connector){
 | 
						|
	case MSP3430_CONNECTOR_2:
 | 
						|
	case MSP3430_CONNECTOR_3:
 | 
						|
	    if (m->c_format!=MSPFORMAT_SCART) {
 | 
						|
    		/* SCART Input Prescale: 0 dB gain */
 | 
						|
			SetMSP3430Data (m, WR_DSP, 0x00, 0x0d, 0x19, 0x00);
 | 
						|
			/* this has not been checked yet.. could be bogus */
 | 
						|
			m->c_format=MSPFORMAT_SCART;	/*stereo*/
 | 
						|
		}
 | 
						|
	    break;
 | 
						|
	case MSP3430_CONNECTOR_1:
 | 
						|
	default:
 | 
						|
	
 | 
						|
	    switch ( m->standard & 0x00ff ) {
 | 
						|
		case MSP3430_PAL:
 | 
						|
			switch( m->standard ) {
 | 
						|
			case MSP3430_PAL_DK1:
 | 
						|
			    standard=MSPSTANDARD_FM_DK1;
 | 
						|
			    break;
 | 
						|
/*			case MSP3430_PAL_DK2:
 | 
						|
			    standard=MSPSTANDARD_FM_DK2;
 | 
						|
			    break;
 | 
						|
			case MSP3430_PAL_BG:
 | 
						|
			may be FM stereo (Germany) or FM NICAM (Scandinavia,spain)
 | 
						|
			    standard=MSPSTANDARD_AUTO;
 | 
						|
			    break;
 | 
						|
*/
 | 
						|
			default:
 | 
						|
			    standard=MSPSTANDARD_AUTO;
 | 
						|
			}
 | 
						|
		    break;
 | 
						|
		case MSP3430_SECAM:
 | 
						|
		    standard=MSPSTANDARD_AUTO;
 | 
						|
		case MSP3430_NTSC:
 | 
						|
			    /* Only MSP34x5 supported format - Korean NTSC-M*/
 | 
						|
			 standard=MSPSTANDARD_FM_M;
 | 
						|
		default:
 | 
						|
		    standard=MSPSTANDARD_AUTO;
 | 
						|
		}
 | 
						|
		
 | 
						|
	    /*no NICAM support in MSP3410D - force to autodetect*/
 | 
						|
	    if ((m->chip_id==0x405) && (standard>=MSPSTANDARD_NICAM_BG))
 | 
						|
    		standard=MSPSTANDARD_AUTO;
 | 
						|
		    
 | 
						|
	    if (m->c_standard != standard) {
 | 
						|
 | 
						|
   	        SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF);
 | 
						|
	        if (standard==MSPSTANDARD_AUTO) {
 | 
						|
			    count = 50; /* time shouldn't exceed 1s, just in case */
 | 
						|
			    do {
 | 
						|
     		        usleep(20000);
 | 
						|
     		        GetMSP3430Data (m, RD_DEM, 0x00, 0x7e, &high, &low);
 | 
						|
			        result = ( high << 8 ) | low;
 | 
						|
     		        --count;
 | 
						|
	    	    } while( result > 0x07ff && count > 0 );
 | 
						|
		    
 | 
						|
		    	if ((result > MSPSTANDARD_AUTO))
 | 
						|
					standard=result;
 | 
						|
		    	else standard=MSPSTANDARD_UNKNOWN;
 | 
						|
#if __MSPDEBUG__ > 1
 | 
						|
				xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Detected audio standard: %d\n",result);
 | 
						|
#endif		    	
 | 
						|
		    	/* result = MSPSTANDARD_NICAM_L can be one of:
 | 
						|
		    	SECAM_L - MSPSTANDARD_NICAM_L
 | 
						|
		    	D/K1 - MSPSTANDARD_FM_DK1
 | 
						|
		    	D/K2 - MSPSTANDARD_FM_DK2
 | 
						|
		    	D/K-NICAM - MSPSTANDARD_NICAM_DK*/
 | 
						|
		    	if( standard == MSPSTANDARD_NICAM_L ) {
 | 
						|
		        	if ((m->standard & 0x00ff)==MSP3430_PAL) {
 | 
						|
			    		/* force PAL D/K  */
 | 
						|
			    		standard=MSPSTANDARD_FM_DK1;
 | 
						|
		            	SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF);
 | 
						|
#if __MSPDEBUG__ > 1
 | 
						|
			        	xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO, "Detected 6.5MHz carrier - forced to D/K1 !!!\n" );
 | 
						|
#endif
 | 
						|
					}
 | 
						|
		    	}
 | 
						|
			}
 | 
						|
			m->c_standard=standard;
 | 
						|
	    } /*end - standard changed*/
 | 
						|
	    else {
 | 
						|
			if (standard<MSPSTANDARD_NICAM_BG) {
 | 
						|
    		    /* get old value of ident. mode register*/
 | 
						|
		    	GetMSP3430Data (m, RD_DSP, 0x00, 0x15, &high, &low);
 | 
						|
    		    /* reset Ident-Filter */
 | 
						|
    		    SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x3F);
 | 
						|
		    	/* put back old value to ident. mode register*/
 | 
						|
    		    SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, low);
 | 
						|
			}
 | 
						|
	    }
 | 
						|
 | 
						|
	    if (standard<=MSPSTANDARD_AUTO) {
 | 
						|
    	   	m->c_format=MSPFORMAT_1xFM;
 | 
						|
	    }
 | 
						|
	    else if (standard<MSPSTANDARD_NICAM_BG) {
 | 
						|
			/* set FM prescale */
 | 
						|
			SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0);
 | 
						|
			/* set FM deemphasis*/
 | 
						|
			SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, ((standard==MSPSTANDARD_FM_M)?0:1), 0);
 | 
						|
		    	
 | 
						|
			/* check if FM2 carrier is present */
 | 
						|
			/*turn off FM DC Notch*/
 | 
						|
			SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x3f);
 | 
						|
			/*matrix source for Quasi-Peak Detector - stereo: ch2->L ch1->R*/
 | 
						|
			SetMSP3430Data (m, WR_DSP, 0x00, 0x0c, 0x00, 0x20);
 | 
						|
			
 | 
						|
			mpause(250);
 | 
						|
   		    GetMSP3430Data (m, RD_DSP, 0x00, 0x1A, &high, &low);
 | 
						|
			peak = (high << 8) | low;
 | 
						|
#if __MSPDEBUG__ > 1
 | 
						|
			xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Second carrier Quasi-Peak detection: %d\n",peak);
 | 
						|
#endif	    	
 | 
						|
			/*turn on FM DC Notch*/
 | 
						|
			SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x00);
 | 
						|
	    	
 | 
						|
			if (peak<5) {
 | 
						|
	    	    /* if second carrier not detected - only mono from first carrier*/
 | 
						|
	    	    m->c_format=MSPFORMAT_1xFM;
 | 
						|
			}
 | 
						|
			else {
 | 
						|
	    	    m->c_format=MSPFORMAT_2xFM;
 | 
						|
    	   	    /*start of FM identification process - FM_WAIT
 | 
						|
	    	    wait at least 0.5s - used 1s - gives beter resolution*/
 | 
						|
    	   	    mpause(1000);
 | 
						|
			}
 | 
						|
	    }
 | 
						|
	    else {
 | 
						|
			if (standard==MSPSTANDARD_NICAM_L) {
 | 
						|
	    	    m->c_format=MSPFORMAT_NICAM_AM;
 | 
						|
		    	/* set AM prescale */
 | 
						|
		    	SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x7C, 0);
 | 
						|
			}
 | 
						|
			else {
 | 
						|
	    	    m->c_format=MSPFORMAT_NICAM_FM;
 | 
						|
		    	/* set FM prescale */
 | 
						|
			    SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0);
 | 
						|
			}
 | 
						|
			/* set FM deemphasis*/
 | 
						|
			SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, 0x00, 0);
 | 
						|
			/* set NICAM prescale to 0dB */
 | 
						|
			SetMSP3430Data (m, WR_DSP, 0x00, 0x10, 0x20, 0);
 | 
						|
	    }
 | 
						|
	    
 | 
						|
	    break;
 | 
						|
	} /*end - case conector*/
 | 
						|
 | 
						|
    CheckModeMSP34x5D(m);
 | 
						|
    
 | 
						|
    /* Set volume to FAST_MUTE. */
 | 
						|
    /*SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00);*/
 | 
						|
    /*set volume*/
 | 
						|
	MSP3430SetVolume(m,m->volume);
 | 
						|
    
 | 
						|
    __MSPBEEP
 | 
						|
 | 
						|
 | 
						|
} /* EnableMSP34x5D ()... */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void CheckModeMSP34x5D(MSP3430Ptr m) {
 | 
						|
    const char stereo_on=25;
 | 
						|
    const char stereo_off=20;
 | 
						|
    const char dual_on=-stereo_on;
 | 
						|
    const char dual_off=-stereo_off;
 | 
						|
    char detect;
 | 
						|
    CARD8 matrix, fmmatrix, source, high, low;
 | 
						|
 | 
						|
    fmmatrix=0;		/*no matrix*/
 | 
						|
    source=0;		/*FM*/
 | 
						|
    switch (m->c_format) {
 | 
						|
	case MSPFORMAT_NICAM_FM:
 | 
						|
	case MSPFORMAT_NICAM_AM:
 | 
						|
	case MSPFORMAT_SCART:
 | 
						|
	    source=( (m->c_format == MSPFORMAT_SCART)?2:1 );
 | 
						|
	    switch (m->mode) {
 | 
						|
		case MSPMODE_MONO:
 | 
						|
		    matrix=0x30;	/*MONO*/
 | 
						|
		    break;
 | 
						|
		case MSPMODE_A:
 | 
						|
		    matrix=0x00;	/*A*/
 | 
						|
		    break;
 | 
						|
		case MSPMODE_B:
 | 
						|
		    matrix=0x10;	/*B*/
 | 
						|
		    break;
 | 
						|
		default:
 | 
						|
		    matrix=0x20;	/*STEREO*/
 | 
						|
		    break;
 | 
						|
		}
 | 
						|
	    break;
 | 
						|
	default:
 | 
						|
	case MSPFORMAT_1xFM:
 | 
						|
	    matrix=0x00;	/*A*/
 | 
						|
	    break;
 | 
						|
	case MSPFORMAT_2xFM:
 | 
						|
	    switch (m->mode) {
 | 
						|
		case MSPMODE_MONO:
 | 
						|
		    matrix=0x30;	/*MONO*/
 | 
						|
		    break;
 | 
						|
		case MSPMODE_STEREO:
 | 
						|
		    matrix=0x20;	/*STEREO*/
 | 
						|
		    fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1);
 | 
						|
		    break;
 | 
						|
		case MSPMODE_AB:
 | 
						|
		    matrix=0x20;	/*STEREO*/
 | 
						|
		    break;
 | 
						|
		case MSPMODE_A:
 | 
						|
		    matrix=0x00;	/*A*/
 | 
						|
		    break;
 | 
						|
		case MSPMODE_B:
 | 
						|
		    matrix=0x10;	/*B*/
 | 
						|
		    break;
 | 
						|
		default:
 | 
						|
    		/*FM_IDENT_CHECK*/
 | 
						|
    		GetMSP3430Data (m, RD_DSP, 0x00, 0x18, &high, &low);
 | 
						|
    		detect=(char)high;
 | 
						|
#if __MSPDEBUG__ > 1
 | 
						|
    		xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Stereo Detection Register: %d\n",detect);
 | 
						|
#endif
 | 
						|
    		if (detect>=((m->c_mode==MSPMODE_STEREO)?stereo_off:stereo_on)) {
 | 
						|
				m->c_mode=MSPMODE_STEREO;
 | 
						|
				matrix=0x20;	/*STEREO*/
 | 
						|
				fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1);
 | 
						|
		    }
 | 
						|
			else if (detect<=((m->c_mode==MSPMODE_AB)?dual_off:dual_on)) {
 | 
						|
				m->c_mode=MSPMODE_AB;
 | 
						|
    			switch (m->mode) {
 | 
						|
			    case MSPMODE_STEREO_AB: matrix=0x20; break;
 | 
						|
			    case MSPMODE_STEREO_B: matrix=0x10; break;
 | 
						|
			    default:
 | 
						|
				case MSPMODE_A: matrix=0x00; break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
    		else {
 | 
						|
				m->c_mode=MSPMODE_MONO;
 | 
						|
				matrix=0x30;	/*MONO*/
 | 
						|
			}
 | 
						|
		    break;
 | 
						|
	    } /* end - case mode*/
 | 
						|
	    break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (m->c_fmmatrix != fmmatrix) {
 | 
						|
        GetMSP3430Data (m, RD_DSP, 0x00, 0x0e, &high, &low);
 | 
						|
		SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, high, fmmatrix);
 | 
						|
		m->c_fmmatrix = fmmatrix;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((m->c_matrix != matrix) || (m->c_source != source)) {
 | 
						|
        /*set chanel source and matrix for loudspeaker*/
 | 
						|
		SetMSP3430Data (m, WR_DSP, 0x00, 0x08, source, matrix);
 | 
						|
    	
 | 
						|
		m->c_matrix = matrix;
 | 
						|
		m->c_source = source;
 | 
						|
    }
 | 
						|
 | 
						|
	if ( ((m->c_format) & 0xF0) == MSPFORMAT_NICAM)
 | 
						|
			SetMSP3430Data (m, WR_DEM, 0x00, 0x21, 0, 1);
 | 
						|
 | 
						|
#if __MSPDEBUG__ > 0
 | 
						|
		    char *msg;
 | 
						|
		    switch (matrix) {
 | 
						|
			case 0x30: /*MONO*/
 | 
						|
			    msg="MONO";
 | 
						|
			    break;
 | 
						|
			case 0x00: /*LEFT*/
 | 
						|
			    msg="MONO/CHANNEL_1";
 | 
						|
			    break;
 | 
						|
			case 0x10: /*RIGHT*/
 | 
						|
			    msg="MONO/CHANNEL_2";
 | 
						|
			    break;
 | 
						|
			case 0x20: /*LEFT*/
 | 
						|
			    msg="STEREO";
 | 
						|
			    break;
 | 
						|
			default:
 | 
						|
			    msg="unknown";
 | 
						|
			    break;
 | 
						|
		    }
 | 
						|
    		    xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Audio mode set to: %s\n",msg);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 |