bktr_audio.c revision 119418
1119418Sobrien/*-
251694Sroger * 1. Redistributions of source code must retain the
351694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
451694Sroger * All rights reserved.
551694Sroger *
651694Sroger * Redistribution and use in source and binary forms, with or without
751694Sroger * modification, are permitted provided that the following conditions
851694Sroger * are met:
951694Sroger * 1. Redistributions of source code must retain the above copyright
1051694Sroger *    notice, this list of conditions and the following disclaimer.
1151694Sroger * 2. Redistributions in binary form must reproduce the above copyright
1251694Sroger *    notice, this list of conditions and the following disclaimer in the
1351694Sroger *    documentation and/or other materials provided with the distribution.
1451694Sroger * 3. All advertising materials mentioning features or use of this software
1551694Sroger *    must display the following acknowledgement:
1651694Sroger *      This product includes software developed by Amancio Hasty and
1751694Sroger *      Roger Hardiman
1851694Sroger * 4. The name of the author may not be used to endorse or promote products
1951694Sroger *    derived from this software without specific prior written permission.
2051694Sroger *
2151694Sroger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2251694Sroger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2351694Sroger * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2451694Sroger * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2551694Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2651694Sroger * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2751694Sroger * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2851694Sroger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2951694Sroger * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3051694Sroger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3151694Sroger * POSSIBILITY OF SUCH DAMAGE.
3251694Sroger */
3351694Sroger
34119418Sobrien#include <sys/cdefs.h>
35119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/bktr/bktr_audio.c 119418 2003-08-24 17:55:58Z obrien $");
36119418Sobrien
37119418Sobrien/*
38119418Sobrien * This is part of the Driver for Video Capture Cards (Frame grabbers)
39119418Sobrien * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
40119418Sobrien * chipset.
41119418Sobrien * Copyright Roger Hardiman and Amancio Hasty.
42119418Sobrien *
43119418Sobrien * bktr_audio : This deals with controlling the audio on TV cards,
44119418Sobrien *                controlling the Audio Multiplexer (audio source selector).
45119418Sobrien *                controlling any MSP34xx stereo audio decoders.
46119418Sobrien *                controlling any DPL35xx dolby surroud sound audio decoders.
47119418Sobrien *                initialising TDA98xx audio devices.
48119418Sobrien *
49119418Sobrien */
50119418Sobrien
51118819Salex#include "opt_bktr.h"               /* Include any kernel config options */
52118819Salex
5351694Sroger#include <sys/param.h>
5451694Sroger#include <sys/systm.h>
5551694Sroger#include <sys/kernel.h>
5651694Sroger#include <sys/vnode.h>
5751694Sroger
5859014Sroger#ifdef __FreeBSD__
5967306Sroger
6067306Sroger#if (__FreeBSD_version < 500000)
6167306Sroger#include <machine/clock.h>              /* for DELAY */
62119277Simp#include <pci/pcivar.h>
63119277Simp#else
64119277Simp#include <dev/pci/pcivar.h>
6567306Sroger#endif
6667306Sroger
6759014Sroger#if (__FreeBSD_version >=300000)
6859014Sroger#include <machine/bus_memio.h>		/* for bus space */
6959014Sroger#include <machine/bus.h>
7059014Sroger#include <sys/bus.h>
7159014Sroger#endif
7262112Sroger#endif
7359014Sroger
7459014Sroger#ifdef __NetBSD__
7562112Sroger#include <sys/proc.h>
7662112Sroger#include <dev/ic/bt8xx.h>	/* NetBSD location of .h files */
7762112Sroger#include <dev/pci/bktr/bktr_reg.h>
7862112Sroger#include <dev/pci/bktr/bktr_core.h>
7962112Sroger#include <dev/pci/bktr/bktr_tuner.h>
8062112Sroger#include <dev/pci/bktr/bktr_card.h>
8162112Sroger#include <dev/pci/bktr/bktr_audio.h>
8259014Sroger#else
8359014Sroger#include <machine/ioctl_meteor.h>	/* Traditional location of .h files */
8451694Sroger#include <machine/ioctl_bt848.h>        /* extensions to ioctl_meteor.h */
8551694Sroger#include <dev/bktr/bktr_reg.h>
8651694Sroger#include <dev/bktr/bktr_core.h>
8751694Sroger#include <dev/bktr/bktr_tuner.h>
8851694Sroger#include <dev/bktr/bktr_card.h>
8951694Sroger#include <dev/bktr/bktr_audio.h>
9062112Sroger#endif
9151694Sroger
9251694Sroger/*
93110237Sorion * Prototypes for the GV_BCTV2 specific functions.
9451694Sroger */
95110237Sorionvoid    set_bctv2_audio( bktr_ptr_t bktr );
96110237Sorionvoid    bctv2_gpio_write( bktr_ptr_t bktr, int port, int val );
97110237Sorion/*int   bctv2_gpio_read( bktr_ptr_t bktr, int port );*/ /* Not used */
9851694Sroger
9951694Sroger/*
10051694Sroger * init_audio_devices
10151694Sroger * Reset any MSP34xx or TDA98xx audio devices.
10251694Sroger */
10351694Srogervoid init_audio_devices( bktr_ptr_t bktr ) {
10451694Sroger
10551694Sroger        /* enable stereo if appropriate on TDA audio chip */
10651694Sroger        if ( bktr->card.dbx )
10751694Sroger                init_BTSC( bktr );
10851694Sroger
10951694Sroger        /* reset the MSP34xx stereo audio chip */
11051694Sroger        if ( bktr->card.msp3400c )
11152593Sroger                msp_dpl_reset( bktr, bktr->msp_addr );
11251694Sroger
11352593Sroger        /* reset the DPL35xx dolby audio chip */
11452593Sroger        if ( bktr->card.dpl3518a )
11552593Sroger                msp_dpl_reset( bktr, bktr->dpl_addr );
11652593Sroger
11751694Sroger}
11851694Sroger
11951694Sroger
12051694Sroger/*
12151694Sroger *
12251694Sroger */
12351694Sroger#define AUDIOMUX_DISCOVER_NOT
12451694Srogerint
12551694Srogerset_audio( bktr_ptr_t bktr, int cmd )
12651694Sroger{
12751694Sroger	u_long		temp;
12851694Sroger	volatile u_char	idx;
12951694Sroger
13051694Sroger#if defined( AUDIOMUX_DISCOVER )
13151694Sroger	if ( cmd >= 200 )
13251694Sroger		cmd -= 200;
13351694Sroger	else
13451694Sroger#endif /* AUDIOMUX_DISCOVER */
13551694Sroger
13651694Sroger	/* check for existance of audio MUXes */
13751694Sroger	if ( !bktr->card.audiomuxs[ 4 ] )
13851694Sroger		return( -1 );
13951694Sroger
14051694Sroger	switch (cmd) {
14151694Sroger	case AUDIO_TUNER:
14251694Sroger#ifdef BKTR_REVERSEMUTE
14351694Sroger		bktr->audio_mux_select = 3;
14451694Sroger#else
14551694Sroger		bktr->audio_mux_select = 0;
14651694Sroger#endif
14751694Sroger
14851694Sroger		if (bktr->reverse_mute )
14951694Sroger		      bktr->audio_mux_select = 0;
15051694Sroger		else
15151694Sroger		    bktr->audio_mux_select = 3;
15251694Sroger
15351694Sroger		break;
15451694Sroger	case AUDIO_EXTERN:
15551694Sroger		bktr->audio_mux_select = 1;
15651694Sroger		break;
15751694Sroger	case AUDIO_INTERN:
15851694Sroger		bktr->audio_mux_select = 2;
15951694Sroger		break;
16051694Sroger	case AUDIO_MUTE:
16151694Sroger		bktr->audio_mute_state = TRUE;	/* set mute */
16251694Sroger		break;
16351694Sroger	case AUDIO_UNMUTE:
16451694Sroger		bktr->audio_mute_state = FALSE;	/* clear mute */
16551694Sroger		break;
16651694Sroger	default:
16762112Sroger		printf("%s: audio cmd error %02x\n", bktr_name(bktr),
16862112Sroger		       cmd);
16951694Sroger		return( -1 );
17051694Sroger	}
17151694Sroger
17251694Sroger
17351694Sroger	/* Most cards have a simple audio multiplexer to select the
17451694Sroger	 * audio source. The I/O_GV card has a more advanced multiplexer
17551694Sroger	 * and requires special handling.
17651694Sroger	 */
177110237Sorion        if ( bktr->bt848_card == CARD_IO_BCTV2 ) {
178110237Sorion                set_bctv2_audio( bktr );
17951694Sroger                return( 0 );
18051694Sroger	}
18151694Sroger
18251694Sroger	/* Proceed with the simpler audio multiplexer code for the majority
18351694Sroger	 * of Bt848 cards.
18451694Sroger	 */
18551694Sroger
18651694Sroger	/*
18751694Sroger	 * Leave the upper bits of the GPIO port alone in case they control
18851694Sroger	 * something like the dbx or teletext chips.  This doesn't guarantee
18951694Sroger	 * success, but follows the rule of least astonishment.
19051694Sroger	 */
19151694Sroger
19251694Sroger	if ( bktr->audio_mute_state == TRUE ) {
19351694Sroger#ifdef BKTR_REVERSEMUTE
19451694Sroger		idx = 0;
19551694Sroger#else
19651694Sroger		idx = 3;
19751694Sroger#endif
19851694Sroger
19951694Sroger		if (bktr->reverse_mute )
20051694Sroger		  idx  = 3;
20151694Sroger		else
20251694Sroger		  idx  = 0;
20351694Sroger
20451694Sroger	}
20551694Sroger	else
20651694Sroger		idx = bktr->audio_mux_select;
20751694Sroger
20868071Sroger
20959014Sroger	temp = INL(bktr, BKTR_GPIO_DATA) & ~bktr->card.gpio_mux_bits;
21051694Sroger#if defined( AUDIOMUX_DISCOVER )
21159014Sroger	OUTL(bktr, BKTR_GPIO_DATA, temp | (cmd & 0xff));
21262112Sroger	printf("%s: cmd: %d audio mux %x temp %x \n", bktr_name(bktr),
21368071Sroger	  	cmd, bktr->card.audiomuxs[ idx ], temp );
21451694Sroger#else
21559014Sroger	OUTL(bktr, BKTR_GPIO_DATA, temp | bktr->card.audiomuxs[ idx ]);
21651694Sroger#endif /* AUDIOMUX_DISCOVER */
21751694Sroger
21868071Sroger
21968071Sroger
22068071Sroger	/* Some new Hauppauge cards do not have an audio mux */
22168071Sroger	/* Instead we use the MSP34xx chip to select TV audio, Line-In */
22268071Sroger	/* FM Radio and Mute */
22368071Sroger	/* Examples of this are the Hauppauge 44xxx MSP34xx models */
22468071Sroger	/* It is ok to drive both the mux and the MSP34xx chip. */
22568071Sroger	/* If there is no mux, the MSP does the switching of the audio source */
22668071Sroger	/* If there is a mux, it does the switching of the audio source */
22768071Sroger
22868071Sroger	if ((bktr->card.msp3400c) && (bktr->audio_mux_present == 0)) {
22968071Sroger
23068071Sroger	  if (bktr->audio_mute_state == TRUE ) {
23168071Sroger		 msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x0000); /* volume to MUTE */
23268071Sroger	  } else {
23368071Sroger		 if(bktr->audio_mux_select == 0) { /* TV Tuner */
23468071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
23568071Sroger		    if (bktr->msp_source_selected != 0) msp_autodetect(bktr);  /* setup TV audio mode */
23668071Sroger		    bktr->msp_source_selected = 0;
23768071Sroger		 }
23868071Sroger		 if(bktr->audio_mux_select == 1) { /* Line In */
23968071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
24068071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000d, 0x1900); /* scart prescale */
24168071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008, 0x0220); /* SCART | STEREO */
24268071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0013, 0x0000); /* DSP In = SC1_IN_L/R */
24368071Sroger		    bktr->msp_source_selected = 1;
24468071Sroger		 }
24568071Sroger
24668071Sroger		 if(bktr->audio_mux_select == 2) { /* FM Radio */
24768071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
24868071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000d, 0x1900); /* scart prescale */
24968071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008, 0x0220); /* SCART | STEREO */
25068071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0013, 0x0200); /* DSP In = SC2_IN_L/R */
25168071Sroger		    bktr->msp_source_selected = 2;
25268071Sroger		 }
25368071Sroger	  }
25468071Sroger	}
25568071Sroger
25668071Sroger
25751694Sroger	return( 0 );
25851694Sroger}
25951694Sroger
26051694Sroger
26151694Sroger/*
26251694Sroger *
26351694Sroger */
26451694Srogervoid
26551694Srogertemp_mute( bktr_ptr_t bktr, int flag )
26651694Sroger{
26751694Sroger	static int	muteState = FALSE;
26851694Sroger
26951694Sroger	if ( flag == TRUE ) {
27051694Sroger		muteState = bktr->audio_mute_state;
27151694Sroger		set_audio( bktr, AUDIO_MUTE );		/* prevent 'click' */
27251694Sroger	}
27351694Sroger	else {
27451694Sroger		tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 );
27551694Sroger		if ( muteState == FALSE )
27651694Sroger			set_audio( bktr, AUDIO_UNMUTE );
27751694Sroger	}
27851694Sroger}
27951694Sroger
28051694Sroger/* address of BTSC/SAP decoder chip */
28151694Sroger#define TDA9850_WADDR           0xb6
28251694Sroger#define TDA9850_RADDR           0xb7
28351694Sroger
28451694Sroger
28551694Sroger/* registers in the TDA9850 BTSC/dbx chip */
28651694Sroger#define CON1ADDR                0x04
28751694Sroger#define CON2ADDR                0x05
28851694Sroger#define CON3ADDR                0x06
28951694Sroger#define CON4ADDR                0x07
29051694Sroger#define ALI1ADDR                0x08
29151694Sroger#define ALI2ADDR                0x09
29251694Sroger#define ALI3ADDR                0x0a
29351694Sroger
29451694Sroger/*
29551694Sroger * initialise the dbx chip
29651694Sroger * taken from the Linux bttv driver TDA9850 initialisation code
29751694Sroger */
29851694Srogervoid
29951694Srogerinit_BTSC( bktr_ptr_t bktr )
30051694Sroger{
30151694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON1ADDR, 0x08); /* noise threshold st */
30251694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON2ADDR, 0x08); /* noise threshold sap */
30351694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON3ADDR, 0x40); /* stereo mode */
30451694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON4ADDR, 0x07); /* 0 dB input gain? */
30551694Sroger    i2cWrite(bktr, TDA9850_WADDR, ALI1ADDR, 0x10); /* wideband alignment? */
30651694Sroger    i2cWrite(bktr, TDA9850_WADDR, ALI2ADDR, 0x10); /* spectral alignment? */
30751694Sroger    i2cWrite(bktr, TDA9850_WADDR, ALI3ADDR, 0x03);
30851694Sroger}
30951694Sroger
31051694Sroger/*
31151694Sroger * setup the dbx chip
31251694Sroger * XXX FIXME: alot of work to be done here, this merely unmutes it.
31351694Sroger */
31451694Srogerint
31551694Srogerset_BTSC( bktr_ptr_t bktr, int control )
31651694Sroger{
31751694Sroger	return( i2cWrite( bktr, TDA9850_WADDR, CON3ADDR, control ) );
31851694Sroger}
31951694Sroger
32051694Sroger/*
321110237Sorion * CARD_GV_BCTV2 specific functions.
32251694Sroger */
32351694Sroger
324110237Sorion#define BCTV2_AUDIO_MAIN              0x10    /* main audio program */
325110237Sorion#define BCTV2_AUDIO_SUB               0x20    /* sub audio program */
326110237Sorion#define BCTV2_AUDIO_BOTH              0x30    /* main(L) + sub(R) program */
32751694Sroger
328110237Sorion#define BCTV2_GPIO_REG0          1
329110237Sorion#define BCTV2_GPIO_REG1          3
33051694Sroger
331110237Sorion#define BCTV2_GR0_AUDIO_MODE     3
332110237Sorion#define BCTV2_GR0_AUDIO_MAIN     0       /* main program */
333110237Sorion#define BCTV2_GR0_AUDIO_SUB      3       /* sub program */
334110237Sorion#define BCTV2_GR0_AUDIO_BOTH     1       /* main(L) + sub(R) */
335110237Sorion#define BCTV2_GR0_AUDIO_MUTE     4       /* audio mute */
336110237Sorion#define BCTV2_GR0_AUDIO_MONO     8       /* force mono */
33751694Sroger
33851694Srogervoid
339110237Sorionset_bctv2_audio( bktr_ptr_t bktr )
34051694Sroger{
34151694Sroger        int data;
34251694Sroger
34351694Sroger        switch (bktr->audio_mux_select) {
34451694Sroger        case 1:         /* external */
34551694Sroger        case 2:         /* internal */
346110237Sorion                bctv2_gpio_write(bktr, BCTV2_GPIO_REG1, 0);
34751694Sroger                break;
34851694Sroger        default:        /* tuner */
349110237Sorion                bctv2_gpio_write(bktr, BCTV2_GPIO_REG1, 1);
35051694Sroger                break;
35151694Sroger        }
35251694Sroger/*      switch (bktr->audio_sap_select) { */
353110237Sorion        switch (BCTV2_AUDIO_BOTH) {
354110237Sorion        case BCTV2_AUDIO_SUB:
355110237Sorion                data = BCTV2_GR0_AUDIO_SUB;
35651694Sroger                break;
357110237Sorion        case BCTV2_AUDIO_BOTH:
358110237Sorion                data = BCTV2_GR0_AUDIO_BOTH;
35951694Sroger                break;
360110237Sorion        case BCTV2_AUDIO_MAIN:
36151694Sroger        default:
362110237Sorion                data = BCTV2_GR0_AUDIO_MAIN;
36351694Sroger                break;
36451694Sroger        }
36551694Sroger        if (bktr->audio_mute_state == TRUE)
366110237Sorion                data |= BCTV2_GR0_AUDIO_MUTE;
36751694Sroger
368110237Sorion        bctv2_gpio_write(bktr, BCTV2_GPIO_REG0, data);
36951694Sroger
37051694Sroger        return;
37151694Sroger}
37251694Sroger
37351694Sroger/* gpio_data bit assignment */
374110237Sorion#define BCTV2_GPIO_ADDR_MASK     0x000300
375110237Sorion#define BCTV2_GPIO_WE            0x000400
376110237Sorion#define BCTV2_GPIO_OE            0x000800
377110237Sorion#define BCTV2_GPIO_VAL_MASK      0x00f000
37851694Sroger
379110237Sorion#define BCTV2_GPIO_PORT_MASK     3
380110237Sorion#define BCTV2_GPIO_ADDR_SHIFT    8
381110237Sorion#define BCTV2_GPIO_VAL_SHIFT     12
38251694Sroger
38351694Sroger/* gpio_out_en value for read/write */
384110237Sorion#define BCTV2_GPIO_OUT_RMASK     0x000f00
385110237Sorion#define BCTV2_GPIO_OUT_WMASK     0x00ff00
38651694Sroger
387110237Sorion#define BCTV2_BITS       100
38851694Sroger
38951694Srogervoid
390110237Sorionbctv2_gpio_write( bktr_ptr_t bktr, int port, int val )
39151694Sroger{
39251694Sroger        u_long data, outbits;
39351694Sroger
394110237Sorion        port &= BCTV2_GPIO_PORT_MASK;
39551694Sroger        switch (port) {
39651694Sroger        case 1:
39751694Sroger        case 3:
398110237Sorion                data = ((val << BCTV2_GPIO_VAL_SHIFT) & BCTV2_GPIO_VAL_MASK) |
399110237Sorion                       ((port << BCTV2_GPIO_ADDR_SHIFT) & BCTV2_GPIO_ADDR_MASK) |
400110237Sorion                       BCTV2_GPIO_WE | BCTV2_GPIO_OE;
401110237Sorion                outbits = BCTV2_GPIO_OUT_WMASK;
40251694Sroger                break;
40351694Sroger        default:
40451694Sroger                return;
40551694Sroger        }
40659014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
40759014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
40859014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, outbits);
409110237Sorion        DELAY(BCTV2_BITS);
410110237Sorion        OUTL(bktr, BKTR_GPIO_DATA, data & ~BCTV2_GPIO_WE);
411110237Sorion        DELAY(BCTV2_BITS);
41259014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
413110237Sorion        DELAY(BCTV2_BITS);
41459014Sroger        OUTL(bktr, BKTR_GPIO_DATA, ~0);
41559014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
41651694Sroger}
41751694Sroger
41851694Sroger/* Not yet used
41951694Srogerint
420110237Sorionbctv2_gpio_read( bktr_ptr_t bktr, int port )
42151694Sroger{
42251694Sroger        u_long data, outbits, ret;
42351694Sroger
424110237Sorion        port &= BCTV2_GPIO_PORT_MASK;
42551694Sroger        switch (port) {
42651694Sroger        case 1:
42751694Sroger        case 3:
428110237Sorion                data = ((port << BCTV2_GPIO_ADDR_SHIFT) & BCTV2_GPIO_ADDR_MASK) |
429110237Sorion                       BCTV2_GPIO_WE | BCTV2_GPIO_OE;
430110237Sorion                outbits = BCTV2_GPIO_OUT_RMASK;
43151694Sroger                break;
43251694Sroger        default:
43351694Sroger                return( -1 );
43451694Sroger        }
43559014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
43659014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
43759014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, outbits);
438110237Sorion        DELAY(BCTV2_BITS);
439110237Sorion        OUTL(bktr, BKTR_GPIO_DATA, data & ~BCTV2_GPIO_OE);
440110237Sorion        DELAY(BCTV2_BITS);
44159014Sroger        ret = INL(bktr, BKTR_GPIO_DATA);
442110237Sorion        DELAY(BCTV2_BITS);
44359014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
444110237Sorion        DELAY(BCTV2_BITS);
44559014Sroger        OUTL(bktr, BKTR_GPIO_DATA, ~0);
44659014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
447110237Sorion        return( (ret & BCTV2_GPIO_VAL_MASK) >> BCTV2_GPIO_VAL_SHIFT );
44851694Sroger}
44951694Sroger*/
45051694Sroger
45151694Sroger/*
45251694Sroger * setup the MSP34xx Stereo Audio Chip
45351694Sroger * This uses the Auto Configuration Option on MSP3410D and MSP3415D chips
45451694Sroger * and DBX mode selection for MSP3430G chips.
45551694Sroger * For MSP3400C support, the full programming sequence is required and is
45651694Sroger * not yet supported.
45751694Sroger */
45851694Sroger
45951694Sroger/* Read the MSP version string */
46051694Srogervoid msp_read_id( bktr_ptr_t bktr ){
46151694Sroger    int rev1=0, rev2=0;
46252593Sroger    rev1 = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x001e);
46352593Sroger    rev2 = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x001f);
46451694Sroger
46551694Sroger    sprintf(bktr->msp_version_string, "34%02d%c-%c%d",
46651694Sroger      (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
46751694Sroger
46851694Sroger}
46951694Sroger
47051694Sroger
47159014Sroger/* Configure the MSP chip to Auto-detect the audio format.
47259014Sroger * For the MSP3430G, we use fast autodetect mode
47359014Sroger * For the MSP3410/3415 there are two schemes for this
47459014Sroger *  a) Fast autodetection - the chip is put into autodetect mode, and the function
47559014Sroger *     returns immediatly. This works in most cases and is the Default Mode.
47659014Sroger *  b) Slow mode. The function sets the MSP3410/3415 chip, then waits for feedback from
47759014Sroger *     the chip and re-programs it if needed.
47859014Sroger */
47951694Srogervoid msp_autodetect( bktr_ptr_t bktr ) {
480118819Salex
481118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER
482118819Salex
483118819Salex  /* Just wake up the (maybe) sleeping thread, it'll do everything for us */
484118819Salex  msp_wake_thread(bktr);
485118819Salex
486118819Salex#else
48759014Sroger  int auto_detect, loops;
48859014Sroger  int stereo;
48951694Sroger
49059014Sroger  /* MSP3430G - countries with mono and DBX stereo */
49151694Sroger  if (strncmp("3430G", bktr->msp_version_string, 5) == 0){
49251694Sroger
49352593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0030,0x2003);/* Enable Auto format detection */
49452593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0020);/* Standard Select Reg. = BTSC-Stereo*/
49552593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000E,0x2403);/* darned if I know */
49652593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0320);/* Source select = (St or A) */
49759014Sroger					                     /* & Ch. Matrix = St */
49852593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
49959014Sroger  }
50051694Sroger
50151694Sroger
50268071Sroger  /* MSP3415D SPECIAL CASE Use the Tuner's Mono audio ouput for the MSP */
50368071Sroger  /* (for Hauppauge 44xxx card with Tuner Type 0x2a) */
50468071Sroger  else if (  ( (strncmp("3415D", bktr->msp_version_string, 5) == 0)
50568071Sroger               &&(bktr->msp_use_mono_source == 1)
50668071Sroger              )
50768071Sroger           || (bktr->slow_msp_audio == 2) ){
50868071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
50968071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000d, 0x1900); /* scart prescale */
51068071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008, 0x0220); /* SCART | STEREO */
51168071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0013, 0x0100); /* DSP In = MONO IN */
51268071Sroger  }
51368071Sroger
51468071Sroger
51559014Sroger  /* MSP3410/MSP3415 - countries with mono, stereo using 2 FM channels and NICAM */
51659014Sroger  /* FAST sound scheme */
51768071Sroger  else if (bktr->slow_msp_audio == 0) {
51852593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
51968071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0000);/* Spkr Source = default(FM/AM) */
52052593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */
52152593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */
52251694Sroger  }
52351694Sroger
52459014Sroger
52559014Sroger  /* MSP3410/MSP3415 - European Countries where the fast MSP3410/3415 programming fails */
52659014Sroger  /* SLOW sound scheme */
52768071Sroger  else if ( bktr->slow_msp_audio == 1) {
52859014Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
52959014Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */
53059014Sroger
53159014Sroger    /* wait for 0.5s max for terrestrial sound autodetection */
53259014Sroger    loops = 10;
53359014Sroger    do {
53459014Sroger      DELAY(100000);
53559014Sroger      auto_detect = msp_dpl_read(bktr, bktr->msp_addr, 0x10, 0x007e);
53659014Sroger      loops++;
53759014Sroger    } while (auto_detect > 0xff && loops < 50);
53862112Sroger    if (bootverbose)printf ("%s: Result of autodetect after %dms: %d\n",
53962112Sroger			    bktr_name(bktr), loops*10, auto_detect);
54059014Sroger
54159014Sroger    /* Now set the audio baseband processing */
54259014Sroger    switch (auto_detect) {
54359014Sroger    case 0:                    /* no TV sound standard detected */
54459014Sroger      break;
54559014Sroger    case 2:                    /* M Dual FM */
54659014Sroger      break;
54759014Sroger    case 3:                    /* B/G Dual FM; German stereo */
54859014Sroger      /* Read the stereo detection value from DSP reg 0x0018 */
54959014Sroger      DELAY(20000);
55059014Sroger      stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
55162112Sroger      if (bootverbose)printf ("%s: Stereo reg 0x18 a: %d\n",
55262112Sroger			      bktr_name(bktr), stereo);
55359014Sroger      DELAY(20000);
55459014Sroger      stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
55562112Sroger      if (bootverbose)printf ("%s: Stereo reg 0x18 b: %d\n",
55662112Sroger			      bktr_name(bktr), stereo);
55759014Sroger      DELAY(20000);
55859014Sroger      stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
55962112Sroger      if (bootverbose)printf ("%s: Stereo reg 0x18 c: %d\n",
56062112Sroger			      bktr_name(bktr), stereo);
56159014Sroger      if (stereo > 0x0100 && stereo < 0x8000) { /* Seems to be stereo */
56259014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0020);/* Loudspeaker set stereo*/
56359014Sroger        /*
56459014Sroger          set spatial effect strength to 50% enlargement
56559014Sroger          set spatial effect mode b, stereo basewidth enlargment only
56659014Sroger        */
56759014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x3f28);
56859014Sroger      } else if (stereo > 0x8000) {    /* bilingual mode */
56962112Sroger        if (bootverbose) printf ("%s: Bilingual mode detected\n",
57062112Sroger				 bktr_name(bktr));
57159014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0000);/* Loudspeaker */
57259014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x0000);/* all spatial effects off */
57359014Sroger       } else {                 /* must be mono */
57459014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0030);/* Loudspeaker */
57559014Sroger        /*
57659014Sroger          set spatial effect strength to 50% enlargement
57759014Sroger          set spatial effect mode a, stereo basewidth enlargment
57859014Sroger          and pseudo stereo effect with automatic high-pass filter
57959014Sroger        */
58059014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x3f08);
58159014Sroger      }
58259014Sroger#if 0
58359014Sroger       /* The reset value for Channel matrix mode is FM/AM and SOUNDA/LEFT */
58459014Sroger       /* We would like STEREO instead val: 0x0020 */
58559014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0020);/* Loudspeaker */
58659014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0009,0x0020);/* Headphone */
58759014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000a,0x0020);/* SCART1 */
58859014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0041,0x0020);/* SCART2 */
58959014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000b,0x0020);/* I2S */
59059014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000c,0x0020);/* Quasi-Peak Detector Source */
59159014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000e,0x0001);
59259014Sroger#endif
59359014Sroger      break;
59459014Sroger    case 8:                    /* B/G FM NICAM */
59559014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */
59659014Sroger       break;
59759014Sroger     case 9:                    /* L_AM NICAM or D/K*/
59859014Sroger     case 10:                   /* i-FM NICAM */
59959014Sroger       break;
60059014Sroger     default:
60162112Sroger       if (bootverbose) printf ("%s: Unknown autodetection result value: %d\n",
60262112Sroger				bktr_name(bktr), auto_detect);
60359014Sroger     }
60459014Sroger
60559014Sroger  }
60659014Sroger
60759014Sroger
60851694Sroger  /* uncomment the following line to enable the MSP34xx 1Khz Tone Generator */
60951694Sroger  /* turn your speaker volume down low before trying this */
61052593Sroger  /* msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0014, 0x7f40); */
611118819Salex
612118819Salex#endif /* BKTR_NEW_MSP34XX_DRIVER */
61351694Sroger}
61452593Sroger
61552593Sroger/* Read the DPL version string */
61652593Srogervoid dpl_read_id( bktr_ptr_t bktr ){
61752593Sroger    int rev1=0, rev2=0;
61852593Sroger    rev1 = msp_dpl_read(bktr, bktr->dpl_addr, 0x12, 0x001e);
61952593Sroger    rev2 = msp_dpl_read(bktr, bktr->dpl_addr, 0x12, 0x001f);
62052593Sroger
62152593Sroger    sprintf(bktr->dpl_version_string, "34%02d%c-%c%d",
62252593Sroger      ((rev2>>8)&0xff)-1, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
62352593Sroger}
62452593Sroger
62552593Sroger/* Configure the DPL chip to Auto-detect the audio format */
62652593Srogervoid dpl_autodetect( bktr_ptr_t bktr ) {
62752593Sroger
62852593Sroger    /* The following are empiric values tried from the DPL35xx data sheet */
62952593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x000c,0x0320);	/* quasi peak detector source dolby
63052593Sroger								lr 0x03xx; quasi peak detector matrix
63152593Sroger								stereo 0xXX20 */
63252593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0040,0x0060);	/* Surround decoder mode;
63352593Sroger								ADAPTIVE/3D-PANORAMA, that means two
63452593Sroger								speakers and no center speaker, all
63552593Sroger								channels L/R/C/S mixed to L and R */
63652593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0041,0x0620);	/* surround source matrix;I2S2/STEREO*/
63752593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0042,0x1F00);	/* surround delay 31ms max */
63852593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0043,0x0000);	/* automatic surround input balance */
63952593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0044,0x4000);	/* surround spatial effect 50%
64052593Sroger								recommended*/
64152593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0045,0x5400);	/* surround panorama effect 66%
64252593Sroger								recommended with PANORAMA mode
64352593Sroger								in 0x0040 set to panorama */
64452593Sroger}
64552593Sroger
646