bktr_audio.c revision 59014
151694Sroger/* $FreeBSD: head/sys/dev/bktr/bktr_audio.c 59014 2000-04-04 16:54:13Z roger $ */
251694Sroger/*
351694Sroger * This is part of the Driver for Video Capture Cards (Frame grabbers)
451694Sroger * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
551694Sroger * chipset.
651694Sroger * Copyright Roger Hardiman and Amancio Hasty.
751694Sroger *
851694Sroger * bktr_audio : This deals with controlling the audio on TV cards,
951694Sroger *                controlling the Audio Multiplexer (audio source selector).
1051694Sroger *                controlling any MSP34xx stereo audio decoders.
1152593Sroger *                controlling any DPL35xx dolby surroud sound audio decoders.
1251694Sroger *                initialising TDA98xx audio devices.
1351694Sroger *
1451694Sroger */
1551694Sroger
1651694Sroger/*
1751694Sroger * 1. Redistributions of source code must retain the
1851694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
1951694Sroger * All rights reserved.
2051694Sroger *
2151694Sroger * Redistribution and use in source and binary forms, with or without
2251694Sroger * modification, are permitted provided that the following conditions
2351694Sroger * are met:
2451694Sroger * 1. Redistributions of source code must retain the above copyright
2551694Sroger *    notice, this list of conditions and the following disclaimer.
2651694Sroger * 2. Redistributions in binary form must reproduce the above copyright
2751694Sroger *    notice, this list of conditions and the following disclaimer in the
2851694Sroger *    documentation and/or other materials provided with the distribution.
2951694Sroger * 3. All advertising materials mentioning features or use of this software
3051694Sroger *    must display the following acknowledgement:
3151694Sroger *      This product includes software developed by Amancio Hasty and
3251694Sroger *      Roger Hardiman
3351694Sroger * 4. The name of the author may not be used to endorse or promote products
3451694Sroger *    derived from this software without specific prior written permission.
3551694Sroger *
3651694Sroger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
3751694Sroger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3851694Sroger * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3951694Sroger * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
4051694Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4151694Sroger * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
4251694Sroger * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4351694Sroger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4451694Sroger * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
4551694Sroger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4651694Sroger * POSSIBILITY OF SUCH DAMAGE.
4751694Sroger */
4851694Sroger
4951694Sroger#include <sys/param.h>
5051694Sroger#include <sys/systm.h>
5151694Sroger#include <sys/kernel.h>
5251694Sroger#include <sys/vnode.h>
5359014Sroger#ifdef __NetBSD__
5459014Sroger#include <sys/proc.h>
5559014Srogerstatic int bootverbose = 1;
5659014Sroger#endif
5751694Sroger
5859014Sroger#ifdef __FreeBSD__
5951694Sroger#include <machine/clock.h>		/* for DELAY */
6051694Sroger#include <pci/pcivar.h>
6159014Sroger#endif
6251694Sroger
6359014Sroger#if (__FreeBSD_version >=300000)
6459014Sroger#include <machine/bus_memio.h>		/* for bus space */
6559014Sroger#include <machine/bus.h>
6659014Sroger#include <sys/bus.h>
6759014Sroger#endif
6859014Sroger
6959014Sroger#ifdef __NetBSD__
7059014Sroger#include <dev/ic/ioctl_meteor.h>	/* NetBSD location of .h files */
7159014Sroger#include <dev/ic/ioctl_bt848.h>
7259014Sroger#else
7359014Sroger#include <machine/ioctl_meteor.h>	/* Traditional location of .h files */
7451694Sroger#include <machine/ioctl_bt848.h>        /* extensions to ioctl_meteor.h */
7559014Sroger#endif
7651694Sroger#include <dev/bktr/bktr_reg.h>
7751694Sroger#include <dev/bktr/bktr_core.h>
7851694Sroger#include <dev/bktr/bktr_tuner.h>
7951694Sroger#include <dev/bktr/bktr_card.h>
8051694Sroger#include <dev/bktr/bktr_audio.h>
8151694Sroger
8251694Sroger
8351694Sroger/*
8451694Sroger * Prototypes for the GV_BCTV specific functions.
8551694Sroger */
8651694Srogervoid    set_bctv_audio( bktr_ptr_t bktr );
8751694Srogervoid    bctv_gpio_write( bktr_ptr_t bktr, int port, int val );
8851694Sroger/*int   bctv_gpio_read( bktr_ptr_t bktr, int port );*/ /* Not used */
8951694Sroger
9051694Sroger
9151694Sroger
9251694Sroger/*
9351694Sroger * init_audio_devices
9451694Sroger * Reset any MSP34xx or TDA98xx audio devices.
9551694Sroger */
9651694Srogervoid init_audio_devices( bktr_ptr_t bktr ) {
9751694Sroger
9851694Sroger        /* enable stereo if appropriate on TDA audio chip */
9951694Sroger        if ( bktr->card.dbx )
10051694Sroger                init_BTSC( bktr );
10151694Sroger
10251694Sroger        /* reset the MSP34xx stereo audio chip */
10351694Sroger        if ( bktr->card.msp3400c )
10452593Sroger                msp_dpl_reset( bktr, bktr->msp_addr );
10551694Sroger
10652593Sroger        /* reset the DPL35xx dolby audio chip */
10752593Sroger        if ( bktr->card.dpl3518a )
10852593Sroger                msp_dpl_reset( bktr, bktr->dpl_addr );
10952593Sroger
11051694Sroger}
11151694Sroger
11251694Sroger
11351694Sroger/*
11451694Sroger *
11551694Sroger */
11651694Sroger#define AUDIOMUX_DISCOVER_NOT
11751694Srogerint
11851694Srogerset_audio( bktr_ptr_t bktr, int cmd )
11951694Sroger{
12051694Sroger	u_long		temp;
12151694Sroger	volatile u_char	idx;
12251694Sroger
12351694Sroger#if defined( AUDIOMUX_DISCOVER )
12451694Sroger	if ( cmd >= 200 )
12551694Sroger		cmd -= 200;
12651694Sroger	else
12751694Sroger#endif /* AUDIOMUX_DISCOVER */
12851694Sroger
12951694Sroger	/* check for existance of audio MUXes */
13051694Sroger	if ( !bktr->card.audiomuxs[ 4 ] )
13151694Sroger		return( -1 );
13251694Sroger
13351694Sroger	switch (cmd) {
13451694Sroger	case AUDIO_TUNER:
13551694Sroger#ifdef BKTR_REVERSEMUTE
13651694Sroger		bktr->audio_mux_select = 3;
13751694Sroger#else
13851694Sroger		bktr->audio_mux_select = 0;
13951694Sroger#endif
14051694Sroger
14151694Sroger		if (bktr->reverse_mute )
14251694Sroger		      bktr->audio_mux_select = 0;
14351694Sroger		else
14451694Sroger		    bktr->audio_mux_select = 3;
14551694Sroger
14651694Sroger		break;
14751694Sroger	case AUDIO_EXTERN:
14851694Sroger		bktr->audio_mux_select = 1;
14951694Sroger		break;
15051694Sroger	case AUDIO_INTERN:
15151694Sroger		bktr->audio_mux_select = 2;
15251694Sroger		break;
15351694Sroger	case AUDIO_MUTE:
15451694Sroger		bktr->audio_mute_state = TRUE;	/* set mute */
15551694Sroger		break;
15651694Sroger	case AUDIO_UNMUTE:
15751694Sroger		bktr->audio_mute_state = FALSE;	/* clear mute */
15851694Sroger		break;
15951694Sroger	default:
16051694Sroger		printf("bktr: audio cmd error %02x\n", cmd);
16151694Sroger		return( -1 );
16251694Sroger	}
16351694Sroger
16451694Sroger
16551694Sroger	/* Most cards have a simple audio multiplexer to select the
16651694Sroger	 * audio source. The I/O_GV card has a more advanced multiplexer
16751694Sroger	 * and requires special handling.
16851694Sroger	 */
16951694Sroger        if ( bktr->bt848_card == CARD_IO_GV ) {
17051694Sroger                set_bctv_audio( bktr );
17151694Sroger                return( 0 );
17251694Sroger	}
17351694Sroger
17451694Sroger	/* Proceed with the simpler audio multiplexer code for the majority
17551694Sroger	 * of Bt848 cards.
17651694Sroger	 */
17751694Sroger
17851694Sroger	/*
17951694Sroger	 * Leave the upper bits of the GPIO port alone in case they control
18051694Sroger	 * something like the dbx or teletext chips.  This doesn't guarantee
18151694Sroger	 * success, but follows the rule of least astonishment.
18251694Sroger	 */
18351694Sroger
18451694Sroger	if ( bktr->audio_mute_state == TRUE ) {
18551694Sroger#ifdef BKTR_REVERSEMUTE
18651694Sroger		idx = 0;
18751694Sroger#else
18851694Sroger		idx = 3;
18951694Sroger#endif
19051694Sroger
19151694Sroger		if (bktr->reverse_mute )
19251694Sroger		  idx  = 3;
19351694Sroger		else
19451694Sroger		  idx  = 0;
19551694Sroger
19651694Sroger	}
19751694Sroger	else
19851694Sroger		idx = bktr->audio_mux_select;
19951694Sroger
20059014Sroger	temp = INL(bktr, BKTR_GPIO_DATA) & ~bktr->card.gpio_mux_bits;
20151694Sroger#if defined( AUDIOMUX_DISCOVER )
20259014Sroger	OUTL(bktr, BKTR_GPIO_DATA, temp | (cmd & 0xff));
20359014Sroger	printf("cmd: %d audio mux %x temp %x \n", cmd,bktr->card.audiomuxs[ idx ], temp );
20451694Sroger#else
20559014Sroger	OUTL(bktr, BKTR_GPIO_DATA, temp | bktr->card.audiomuxs[ idx ]);
20651694Sroger#endif /* AUDIOMUX_DISCOVER */
20751694Sroger
20851694Sroger	return( 0 );
20951694Sroger}
21051694Sroger
21151694Sroger
21251694Sroger/*
21351694Sroger *
21451694Sroger */
21551694Srogervoid
21651694Srogertemp_mute( bktr_ptr_t bktr, int flag )
21751694Sroger{
21851694Sroger	static int	muteState = FALSE;
21951694Sroger
22051694Sroger	if ( flag == TRUE ) {
22151694Sroger		muteState = bktr->audio_mute_state;
22251694Sroger		set_audio( bktr, AUDIO_MUTE );		/* prevent 'click' */
22351694Sroger	}
22451694Sroger	else {
22551694Sroger		tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 );
22651694Sroger		if ( muteState == FALSE )
22751694Sroger			set_audio( bktr, AUDIO_UNMUTE );
22851694Sroger	}
22951694Sroger}
23051694Sroger
23151694Sroger/* address of BTSC/SAP decoder chip */
23251694Sroger#define TDA9850_WADDR           0xb6
23351694Sroger#define TDA9850_RADDR           0xb7
23451694Sroger
23551694Sroger
23651694Sroger/* registers in the TDA9850 BTSC/dbx chip */
23751694Sroger#define CON1ADDR                0x04
23851694Sroger#define CON2ADDR                0x05
23951694Sroger#define CON3ADDR                0x06
24051694Sroger#define CON4ADDR                0x07
24151694Sroger#define ALI1ADDR                0x08
24251694Sroger#define ALI2ADDR                0x09
24351694Sroger#define ALI3ADDR                0x0a
24451694Sroger
24551694Sroger/*
24651694Sroger * initialise the dbx chip
24751694Sroger * taken from the Linux bttv driver TDA9850 initialisation code
24851694Sroger */
24951694Srogervoid
25051694Srogerinit_BTSC( bktr_ptr_t bktr )
25151694Sroger{
25251694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON1ADDR, 0x08); /* noise threshold st */
25351694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON2ADDR, 0x08); /* noise threshold sap */
25451694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON3ADDR, 0x40); /* stereo mode */
25551694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON4ADDR, 0x07); /* 0 dB input gain? */
25651694Sroger    i2cWrite(bktr, TDA9850_WADDR, ALI1ADDR, 0x10); /* wideband alignment? */
25751694Sroger    i2cWrite(bktr, TDA9850_WADDR, ALI2ADDR, 0x10); /* spectral alignment? */
25851694Sroger    i2cWrite(bktr, TDA9850_WADDR, ALI3ADDR, 0x03);
25951694Sroger}
26051694Sroger
26151694Sroger/*
26251694Sroger * setup the dbx chip
26351694Sroger * XXX FIXME: alot of work to be done here, this merely unmutes it.
26451694Sroger */
26551694Srogerint
26651694Srogerset_BTSC( bktr_ptr_t bktr, int control )
26751694Sroger{
26851694Sroger	return( i2cWrite( bktr, TDA9850_WADDR, CON3ADDR, control ) );
26951694Sroger}
27051694Sroger
27151694Sroger/*
27251694Sroger * CARD_GV_BCTV specific functions.
27351694Sroger */
27451694Sroger
27551694Sroger#define BCTV_AUDIO_MAIN              0x10    /* main audio program */
27651694Sroger#define BCTV_AUDIO_SUB               0x20    /* sub audio program */
27751694Sroger#define BCTV_AUDIO_BOTH              0x30    /* main(L) + sub(R) program */
27851694Sroger
27951694Sroger#define BCTV_GPIO_REG0          1
28051694Sroger#define BCTV_GPIO_REG1          3
28151694Sroger
28251694Sroger#define BCTV_GR0_AUDIO_MODE     3
28351694Sroger#define BCTV_GR0_AUDIO_MAIN     0       /* main program */
28451694Sroger#define BCTV_GR0_AUDIO_SUB      3       /* sub program */
28551694Sroger#define BCTV_GR0_AUDIO_BOTH     1       /* main(L) + sub(R) */
28651694Sroger#define BCTV_GR0_AUDIO_MUTE     4       /* audio mute */
28751694Sroger#define BCTV_GR0_AUDIO_MONO     8       /* force mono */
28851694Sroger
28951694Srogervoid
29051694Srogerset_bctv_audio( bktr_ptr_t bktr )
29151694Sroger{
29251694Sroger        int data;
29351694Sroger
29451694Sroger        switch (bktr->audio_mux_select) {
29551694Sroger        case 1:         /* external */
29651694Sroger        case 2:         /* internal */
29751694Sroger                bctv_gpio_write(bktr, BCTV_GPIO_REG1, 0);
29851694Sroger                break;
29951694Sroger        default:        /* tuner */
30051694Sroger                bctv_gpio_write(bktr, BCTV_GPIO_REG1, 1);
30151694Sroger                break;
30251694Sroger        }
30351694Sroger/*      switch (bktr->audio_sap_select) { */
30451694Sroger        switch (BCTV_AUDIO_BOTH) {
30551694Sroger        case BCTV_AUDIO_SUB:
30651694Sroger                data = BCTV_GR0_AUDIO_SUB;
30751694Sroger                break;
30851694Sroger        case BCTV_AUDIO_BOTH:
30951694Sroger                data = BCTV_GR0_AUDIO_BOTH;
31051694Sroger                break;
31151694Sroger        case BCTV_AUDIO_MAIN:
31251694Sroger        default:
31351694Sroger                data = BCTV_GR0_AUDIO_MAIN;
31451694Sroger                break;
31551694Sroger        }
31651694Sroger        if (bktr->audio_mute_state == TRUE)
31751694Sroger                data |= BCTV_GR0_AUDIO_MUTE;
31851694Sroger
31951694Sroger        bctv_gpio_write(bktr, BCTV_GPIO_REG0, data);
32051694Sroger
32151694Sroger        return;
32251694Sroger}
32351694Sroger
32451694Sroger/* gpio_data bit assignment */
32551694Sroger#define BCTV_GPIO_ADDR_MASK     0x000300
32651694Sroger#define BCTV_GPIO_WE            0x000400
32751694Sroger#define BCTV_GPIO_OE            0x000800
32851694Sroger#define BCTV_GPIO_VAL_MASK      0x00f000
32951694Sroger
33051694Sroger#define BCTV_GPIO_PORT_MASK     3
33151694Sroger#define BCTV_GPIO_ADDR_SHIFT    8
33251694Sroger#define BCTV_GPIO_VAL_SHIFT     12
33351694Sroger
33451694Sroger/* gpio_out_en value for read/write */
33551694Sroger#define BCTV_GPIO_OUT_RMASK     0x000f00
33651694Sroger#define BCTV_GPIO_OUT_WMASK     0x00ff00
33751694Sroger
33851694Sroger#define BCTV_BITS       100
33951694Sroger
34051694Srogervoid
34151694Srogerbctv_gpio_write( bktr_ptr_t bktr, int port, int val )
34251694Sroger{
34351694Sroger        u_long data, outbits;
34451694Sroger
34551694Sroger        port &= BCTV_GPIO_PORT_MASK;
34651694Sroger        switch (port) {
34751694Sroger        case 1:
34851694Sroger        case 3:
34951694Sroger                data = ((val << BCTV_GPIO_VAL_SHIFT) & BCTV_GPIO_VAL_MASK) |
35051694Sroger                       ((port << BCTV_GPIO_ADDR_SHIFT) & BCTV_GPIO_ADDR_MASK) |
35151694Sroger                       BCTV_GPIO_WE | BCTV_GPIO_OE;
35251694Sroger                outbits = BCTV_GPIO_OUT_WMASK;
35351694Sroger                break;
35451694Sroger        default:
35551694Sroger                return;
35651694Sroger        }
35759014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
35859014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
35959014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, outbits);
36051694Sroger        DELAY(BCTV_BITS);
36159014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data & ~BCTV_GPIO_WE);
36251694Sroger        DELAY(BCTV_BITS);
36359014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
36451694Sroger        DELAY(BCTV_BITS);
36559014Sroger        OUTL(bktr, BKTR_GPIO_DATA, ~0);
36659014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
36751694Sroger}
36851694Sroger
36951694Sroger/* Not yet used
37051694Srogerint
37151694Srogerbctv_gpio_read( bktr_ptr_t bktr, int port )
37251694Sroger{
37351694Sroger        u_long data, outbits, ret;
37451694Sroger
37551694Sroger        port &= BCTV_GPIO_PORT_MASK;
37651694Sroger        switch (port) {
37751694Sroger        case 1:
37851694Sroger        case 3:
37951694Sroger                data = ((port << BCTV_GPIO_ADDR_SHIFT) & BCTV_GPIO_ADDR_MASK) |
38051694Sroger                       BCTV_GPIO_WE | BCTV_GPIO_OE;
38151694Sroger                outbits = BCTV_GPIO_OUT_RMASK;
38251694Sroger                break;
38351694Sroger        default:
38451694Sroger                return( -1 );
38551694Sroger        }
38659014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
38759014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
38859014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, outbits);
38951694Sroger        DELAY(BCTV_BITS);
39059014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data & ~BCTV_GPIO_OE);
39151694Sroger        DELAY(BCTV_BITS);
39259014Sroger        ret = INL(bktr, BKTR_GPIO_DATA);
39351694Sroger        DELAY(BCTV_BITS);
39459014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
39551694Sroger        DELAY(BCTV_BITS);
39659014Sroger        OUTL(bktr, BKTR_GPIO_DATA, ~0);
39759014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
39851694Sroger        return( (ret & BCTV_GPIO_VAL_MASK) >> BCTV_GPIO_VAL_SHIFT );
39951694Sroger}
40051694Sroger*/
40151694Sroger
40251694Sroger/*
40351694Sroger * setup the MSP34xx Stereo Audio Chip
40451694Sroger * This uses the Auto Configuration Option on MSP3410D and MSP3415D chips
40551694Sroger * and DBX mode selection for MSP3430G chips.
40651694Sroger * For MSP3400C support, the full programming sequence is required and is
40751694Sroger * not yet supported.
40851694Sroger */
40951694Sroger
41051694Sroger/* Read the MSP version string */
41151694Srogervoid msp_read_id( bktr_ptr_t bktr ){
41251694Sroger    int rev1=0, rev2=0;
41352593Sroger    rev1 = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x001e);
41452593Sroger    rev2 = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x001f);
41551694Sroger
41651694Sroger    sprintf(bktr->msp_version_string, "34%02d%c-%c%d",
41751694Sroger      (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
41851694Sroger
41951694Sroger}
42051694Sroger
42151694Sroger
42259014Sroger/* Configure the MSP chip to Auto-detect the audio format.
42359014Sroger * For the MSP3430G, we use fast autodetect mode
42459014Sroger * For the MSP3410/3415 there are two schemes for this
42559014Sroger *  a) Fast autodetection - the chip is put into autodetect mode, and the function
42659014Sroger *     returns immediatly. This works in most cases and is the Default Mode.
42759014Sroger *  b) Slow mode. The function sets the MSP3410/3415 chip, then waits for feedback from
42859014Sroger *     the chip and re-programs it if needed.
42959014Sroger */
43051694Srogervoid msp_autodetect( bktr_ptr_t bktr ) {
43159014Sroger  int auto_detect, loops;
43259014Sroger  int stereo;
43359014Sroger  printf("MSP autodetect\n");
43451694Sroger
43559014Sroger  /* MSP3430G - countries with mono and DBX stereo */
43651694Sroger  if (strncmp("3430G", bktr->msp_version_string, 5) == 0){
43751694Sroger
43852593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0030,0x2003);/* Enable Auto format detection */
43952593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0020);/* Standard Select Reg. = BTSC-Stereo*/
44052593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000E,0x2403);/* darned if I know */
44152593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0320);/* Source select = (St or A) */
44259014Sroger					                     /* & Ch. Matrix = St */
44352593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
44459014Sroger  }
44551694Sroger
44651694Sroger
44759014Sroger  /* MSP3410/MSP3415 - countries with mono, stereo using 2 FM channels and NICAM */
44859014Sroger  /* FAST sound scheme */
44959014Sroger  if ( (strncmp("3430G", bktr->msp_version_string, 5) != 0)
45059014Sroger    && (bktr->slow_msp_audio == 0) ){
45159014Sroger    if(bootverbose)printf("inside fast MSP autodetect code\n");
45252593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
45352593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */
45452593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */
45551694Sroger  }
45651694Sroger
45759014Sroger
45859014Sroger  /* MSP3410/MSP3415 - European Countries where the fast MSP3410/3415 programming fails */
45959014Sroger  /* SLOW sound scheme */
46059014Sroger  if ( (strncmp("3430G", bktr->msp_version_string, 5) != 0)
46159014Sroger    && (bktr->slow_msp_audio == 1) ){
46259014Sroger    if (bootverbose)printf("inside slow MSP autodetect code\n");
46359014Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
46459014Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */
46559014Sroger
46659014Sroger    /* wait for 0.5s max for terrestrial sound autodetection */
46759014Sroger    loops = 10;
46859014Sroger    do {
46959014Sroger      DELAY(100000);
47059014Sroger      auto_detect = msp_dpl_read(bktr, bktr->msp_addr, 0x10, 0x007e);
47159014Sroger      loops++;
47259014Sroger    } while (auto_detect > 0xff && loops < 50);
47359014Sroger    if (bootverbose)printf ("Result of autodetect after %dms: %d\n", loops*10, auto_detect);
47459014Sroger
47559014Sroger    /* Now set the audio baseband processing */
47659014Sroger    switch (auto_detect) {
47759014Sroger    case 0:                    /* no TV sound standard detected */
47859014Sroger      break;
47959014Sroger    case 2:                    /* M Dual FM */
48059014Sroger      break;
48159014Sroger    case 3:                    /* B/G Dual FM; German stereo */
48259014Sroger      /* Read the stereo detection value from DSP reg 0x0018 */
48359014Sroger      DELAY(20000);
48459014Sroger      stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
48559014Sroger      if (bootverbose)printf ("Stereo reg 0x18 a: %d\n", stereo);
48659014Sroger      DELAY(20000);
48759014Sroger      stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
48859014Sroger      if (bootverbose)printf ("Stereo reg 0x18 b: %d\n", stereo);
48959014Sroger      DELAY(20000);
49059014Sroger      stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
49159014Sroger      if (bootverbose)printf ("Stereo reg 0x18 c: %d\n", stereo);
49259014Sroger      if (stereo > 0x0100 && stereo < 0x8000) { /* Seems to be stereo */
49359014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0020);/* Loudspeaker set stereo*/
49459014Sroger        /*
49559014Sroger          set spatial effect strength to 50% enlargement
49659014Sroger          set spatial effect mode b, stereo basewidth enlargment only
49759014Sroger        */
49859014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x3f28);
49959014Sroger      } else if (stereo > 0x8000) {    /* bilingual mode */
50059014Sroger        if (bootverbose) printf ("Bilingual mode detected\n");
50159014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0000);/* Loudspeaker */
50259014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x0000);/* all spatial effects off */
50359014Sroger       } else {                 /* must be mono */
50459014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0030);/* Loudspeaker */
50559014Sroger        /*
50659014Sroger          set spatial effect strength to 50% enlargement
50759014Sroger          set spatial effect mode a, stereo basewidth enlargment
50859014Sroger          and pseudo stereo effect with automatic high-pass filter
50959014Sroger        */
51059014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x3f08);
51159014Sroger      }
51259014Sroger#if 0
51359014Sroger       /* The reset value for Channel matrix mode is FM/AM and SOUNDA/LEFT */
51459014Sroger       /* We would like STEREO instead val: 0x0020 */
51559014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0020);/* Loudspeaker */
51659014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0009,0x0020);/* Headphone */
51759014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000a,0x0020);/* SCART1 */
51859014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0041,0x0020);/* SCART2 */
51959014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000b,0x0020);/* I2S */
52059014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000c,0x0020);/* Quasi-Peak Detector Source */
52159014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000e,0x0001);
52259014Sroger#endif
52359014Sroger      break;
52459014Sroger    case 8:                    /* B/G FM NICAM */
52559014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */
52659014Sroger       break;
52759014Sroger     case 9:                    /* L_AM NICAM or D/K*/
52859014Sroger     case 10:                   /* i-FM NICAM */
52959014Sroger       break;
53059014Sroger     default:
53159014Sroger       if (bootverbose) printf ("Unkown autodetection result value: %d\n", auto_detect);
53259014Sroger     }
53359014Sroger
53459014Sroger  }
53559014Sroger
53659014Sroger
53751694Sroger  /* uncomment the following line to enable the MSP34xx 1Khz Tone Generator */
53851694Sroger  /* turn your speaker volume down low before trying this */
53952593Sroger  /* msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0014, 0x7f40); */
54051694Sroger}
54152593Sroger
54252593Sroger/* Read the DPL version string */
54352593Srogervoid dpl_read_id( bktr_ptr_t bktr ){
54452593Sroger    int rev1=0, rev2=0;
54552593Sroger    rev1 = msp_dpl_read(bktr, bktr->dpl_addr, 0x12, 0x001e);
54652593Sroger    rev2 = msp_dpl_read(bktr, bktr->dpl_addr, 0x12, 0x001f);
54752593Sroger
54852593Sroger    sprintf(bktr->dpl_version_string, "34%02d%c-%c%d",
54952593Sroger      ((rev2>>8)&0xff)-1, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
55052593Sroger}
55152593Sroger
55252593Sroger/* Configure the DPL chip to Auto-detect the audio format */
55352593Srogervoid dpl_autodetect( bktr_ptr_t bktr ) {
55452593Sroger
55552593Sroger    /* The following are empiric values tried from the DPL35xx data sheet */
55652593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x000c,0x0320);	/* quasi peak detector source dolby
55752593Sroger								lr 0x03xx; quasi peak detector matrix
55852593Sroger								stereo 0xXX20 */
55952593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0040,0x0060);	/* Surround decoder mode;
56052593Sroger								ADAPTIVE/3D-PANORAMA, that means two
56152593Sroger								speakers and no center speaker, all
56252593Sroger								channels L/R/C/S mixed to L and R */
56352593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0041,0x0620);	/* surround source matrix;I2S2/STEREO*/
56452593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0042,0x1F00);	/* surround delay 31ms max */
56552593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0043,0x0000);	/* automatic surround input balance */
56652593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0044,0x4000);	/* surround spatial effect 50%
56752593Sroger								recommended*/
56852593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0045,0x5400);	/* surround panorama effect 66%
56952593Sroger								recommended with PANORAMA mode
57052593Sroger								in 0x0040 set to panorama */
57152593Sroger}
57252593Sroger
573