xserver-multidpi/hw/xfree86/i2c/msp3430.c
Keith Packard 9838b7032e Introduce a consistent coding style
This is strictly the application of the script 'x-indent-all.sh'
from util/modular. Compared to the patch that Daniel posted in
January, I've added a few indent flags:

	-bap
	-psl
	-T PrivatePtr
	-T pmWait
	-T _XFUNCPROTOBEGIN
	-T _XFUNCPROTOEND
	-T _X_EXPORT

The typedefs were needed to make the output of sdksyms.sh match the
previous output, otherwise, the code is formatted badly enough that
sdksyms.sh generates incorrect output.

The generated code was compared with the previous version and found to
be essentially identical -- "assert" line numbers and BUILD_TIME were
the only differences found.

The comparison was done with this script:

dir1=$1
dir2=$2

for dir in $dir1 $dir2; do
	(cd $dir && find . -name '*.o' | while read file; do
		dir=`dirname $file`
		base=`basename $file .o`
		dump=$dir/$base.dump
		objdump -d $file > $dump
	done)
done

find $dir1 -name '*.dump' | while read dump; do
	otherdump=`echo $dump | sed "s;$dir1;$dir2;"`
	diff -u $dump $otherdump
done

Signed-off-by: Keith Packard <keithp@keithp.com>
Acked-by: Daniel Stone <daniel@fooishbar.org>
Acked-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2012-03-21 13:54:42 -07:00

780 lines
23 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);
static const 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
static const 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
}