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$");
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
5759014Sroger#ifdef __FreeBSD__
5867306Sroger
5967306Sroger#if (__FreeBSD_version < 500000)
6067306Sroger#include <machine/clock.h>              /* for DELAY */
61119277Simp#include <pci/pcivar.h>
62119277Simp#else
63139917Simp#include <sys/lock.h>
64139917Simp#include <sys/mutex.h>
65139917Simp#include <sys/selinfo.h>
66119277Simp#include <dev/pci/pcivar.h>
6767306Sroger#endif
6867306Sroger
6959014Sroger#include <machine/bus.h>
7059014Sroger#include <sys/bus.h>
7159014Sroger#endif
7259014Sroger
7359014Sroger#ifdef __NetBSD__
7462112Sroger#include <sys/proc.h>
7562112Sroger#include <dev/ic/bt8xx.h>	/* NetBSD location of .h files */
7662112Sroger#include <dev/pci/bktr/bktr_reg.h>
7762112Sroger#include <dev/pci/bktr/bktr_core.h>
7862112Sroger#include <dev/pci/bktr/bktr_tuner.h>
7962112Sroger#include <dev/pci/bktr/bktr_card.h>
8062112Sroger#include <dev/pci/bktr/bktr_audio.h>
8159014Sroger#else
82123291Sobrien#include <dev/bktr/ioctl_meteor.h>
83123291Sobrien#include <dev/bktr/ioctl_bt848.h>	/* extensions to ioctl_meteor.h */
8451694Sroger#include <dev/bktr/bktr_reg.h>
8551694Sroger#include <dev/bktr/bktr_core.h>
8651694Sroger#include <dev/bktr/bktr_tuner.h>
8751694Sroger#include <dev/bktr/bktr_card.h>
8851694Sroger#include <dev/bktr/bktr_audio.h>
8962112Sroger#endif
9051694Sroger
9151694Sroger/*
92110237Sorion * Prototypes for the GV_BCTV2 specific functions.
9351694Sroger */
94110237Sorionvoid    set_bctv2_audio( bktr_ptr_t bktr );
95110237Sorionvoid    bctv2_gpio_write( bktr_ptr_t bktr, int port, int val );
96110237Sorion/*int   bctv2_gpio_read( bktr_ptr_t bktr, int port );*/ /* Not used */
9751694Sroger
9851694Sroger/*
9951694Sroger * init_audio_devices
10051694Sroger * Reset any MSP34xx or TDA98xx audio devices.
10151694Sroger */
10251694Srogervoid init_audio_devices( bktr_ptr_t bktr ) {
10351694Sroger
10451694Sroger        /* enable stereo if appropriate on TDA audio chip */
10551694Sroger        if ( bktr->card.dbx )
10651694Sroger                init_BTSC( bktr );
10751694Sroger
10851694Sroger        /* reset the MSP34xx stereo audio chip */
10951694Sroger        if ( bktr->card.msp3400c )
11052593Sroger                msp_dpl_reset( bktr, bktr->msp_addr );
11151694Sroger
11252593Sroger        /* reset the DPL35xx dolby audio chip */
11352593Sroger        if ( bktr->card.dpl3518a )
11452593Sroger                msp_dpl_reset( bktr, bktr->dpl_addr );
11552593Sroger
11651694Sroger}
11751694Sroger
11851694Sroger
11951694Sroger/*
12051694Sroger *
12151694Sroger */
12251694Sroger#define AUDIOMUX_DISCOVER_NOT
12351694Srogerint
12451694Srogerset_audio( bktr_ptr_t bktr, int cmd )
12551694Sroger{
12651694Sroger	u_long		temp;
12751694Sroger	volatile u_char	idx;
12851694Sroger
12951694Sroger#if defined( AUDIOMUX_DISCOVER )
13051694Sroger	if ( cmd >= 200 )
13151694Sroger		cmd -= 200;
13251694Sroger	else
13351694Sroger#endif /* AUDIOMUX_DISCOVER */
13451694Sroger
13551694Sroger	/* check for existance of audio MUXes */
13651694Sroger	if ( !bktr->card.audiomuxs[ 4 ] )
13751694Sroger		return( -1 );
13851694Sroger
13951694Sroger	switch (cmd) {
14051694Sroger	case AUDIO_TUNER:
14151694Sroger#ifdef BKTR_REVERSEMUTE
14251694Sroger		bktr->audio_mux_select = 3;
14351694Sroger#else
14451694Sroger		bktr->audio_mux_select = 0;
14551694Sroger#endif
14651694Sroger
14751694Sroger		if (bktr->reverse_mute )
14851694Sroger		      bktr->audio_mux_select = 0;
14951694Sroger		else
15051694Sroger		    bktr->audio_mux_select = 3;
15151694Sroger
15251694Sroger		break;
15351694Sroger	case AUDIO_EXTERN:
15451694Sroger		bktr->audio_mux_select = 1;
15551694Sroger		break;
15651694Sroger	case AUDIO_INTERN:
15751694Sroger		bktr->audio_mux_select = 2;
15851694Sroger		break;
15951694Sroger	case AUDIO_MUTE:
16051694Sroger		bktr->audio_mute_state = TRUE;	/* set mute */
16151694Sroger		break;
16251694Sroger	case AUDIO_UNMUTE:
16351694Sroger		bktr->audio_mute_state = FALSE;	/* clear mute */
16451694Sroger		break;
16551694Sroger	default:
16662112Sroger		printf("%s: audio cmd error %02x\n", bktr_name(bktr),
16762112Sroger		       cmd);
16851694Sroger		return( -1 );
16951694Sroger	}
17051694Sroger
17151694Sroger
17251694Sroger	/* Most cards have a simple audio multiplexer to select the
17351694Sroger	 * audio source. The I/O_GV card has a more advanced multiplexer
17451694Sroger	 * and requires special handling.
17551694Sroger	 */
176110237Sorion        if ( bktr->bt848_card == CARD_IO_BCTV2 ) {
177110237Sorion                set_bctv2_audio( bktr );
17851694Sroger                return( 0 );
17951694Sroger	}
18051694Sroger
18151694Sroger	/* Proceed with the simpler audio multiplexer code for the majority
18251694Sroger	 * of Bt848 cards.
18351694Sroger	 */
18451694Sroger
18551694Sroger	/*
18651694Sroger	 * Leave the upper bits of the GPIO port alone in case they control
18751694Sroger	 * something like the dbx or teletext chips.  This doesn't guarantee
18851694Sroger	 * success, but follows the rule of least astonishment.
18951694Sroger	 */
19051694Sroger
19151694Sroger	if ( bktr->audio_mute_state == TRUE ) {
19251694Sroger#ifdef BKTR_REVERSEMUTE
19351694Sroger		idx = 0;
19451694Sroger#else
19551694Sroger		idx = 3;
19651694Sroger#endif
19751694Sroger
19851694Sroger		if (bktr->reverse_mute )
19951694Sroger		  idx  = 3;
20051694Sroger		else
20151694Sroger		  idx  = 0;
20251694Sroger
20351694Sroger	}
20451694Sroger	else
20551694Sroger		idx = bktr->audio_mux_select;
20651694Sroger
20768071Sroger
20859014Sroger	temp = INL(bktr, BKTR_GPIO_DATA) & ~bktr->card.gpio_mux_bits;
20951694Sroger#if defined( AUDIOMUX_DISCOVER )
21059014Sroger	OUTL(bktr, BKTR_GPIO_DATA, temp | (cmd & 0xff));
21162112Sroger	printf("%s: cmd: %d audio mux %x temp %x \n", bktr_name(bktr),
21268071Sroger	  	cmd, bktr->card.audiomuxs[ idx ], temp );
21351694Sroger#else
21459014Sroger	OUTL(bktr, BKTR_GPIO_DATA, temp | bktr->card.audiomuxs[ idx ]);
21551694Sroger#endif /* AUDIOMUX_DISCOVER */
21651694Sroger
21768071Sroger
21868071Sroger
21968071Sroger	/* Some new Hauppauge cards do not have an audio mux */
22068071Sroger	/* Instead we use the MSP34xx chip to select TV audio, Line-In */
22168071Sroger	/* FM Radio and Mute */
22268071Sroger	/* Examples of this are the Hauppauge 44xxx MSP34xx models */
22368071Sroger	/* It is ok to drive both the mux and the MSP34xx chip. */
22468071Sroger	/* If there is no mux, the MSP does the switching of the audio source */
22568071Sroger	/* If there is a mux, it does the switching of the audio source */
22668071Sroger
22768071Sroger	if ((bktr->card.msp3400c) && (bktr->audio_mux_present == 0)) {
22868071Sroger
22968071Sroger	  if (bktr->audio_mute_state == TRUE ) {
23068071Sroger		 msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x0000); /* volume to MUTE */
23168071Sroger	  } else {
23268071Sroger		 if(bktr->audio_mux_select == 0) { /* TV Tuner */
23368071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
23468071Sroger		    if (bktr->msp_source_selected != 0) msp_autodetect(bktr);  /* setup TV audio mode */
23568071Sroger		    bktr->msp_source_selected = 0;
23668071Sroger		 }
23768071Sroger		 if(bktr->audio_mux_select == 1) { /* Line In */
23868071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
23968071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000d, 0x1900); /* scart prescale */
24068071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008, 0x0220); /* SCART | STEREO */
24168071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0013, 0x0000); /* DSP In = SC1_IN_L/R */
24268071Sroger		    bktr->msp_source_selected = 1;
24368071Sroger		 }
24468071Sroger
24568071Sroger		 if(bktr->audio_mux_select == 2) { /* FM Radio */
24668071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
24768071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000d, 0x1900); /* scart prescale */
24868071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008, 0x0220); /* SCART | STEREO */
24968071Sroger		    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0013, 0x0200); /* DSP In = SC2_IN_L/R */
25068071Sroger		    bktr->msp_source_selected = 2;
25168071Sroger		 }
25268071Sroger	  }
25368071Sroger	}
25468071Sroger
25568071Sroger
25651694Sroger	return( 0 );
25751694Sroger}
25851694Sroger
25951694Sroger
26051694Sroger/*
26151694Sroger *
26251694Sroger */
26351694Srogervoid
26451694Srogertemp_mute( bktr_ptr_t bktr, int flag )
26551694Sroger{
26651694Sroger	static int	muteState = FALSE;
26751694Sroger
26851694Sroger	if ( flag == TRUE ) {
26951694Sroger		muteState = bktr->audio_mute_state;
27051694Sroger		set_audio( bktr, AUDIO_MUTE );		/* prevent 'click' */
27151694Sroger	}
27251694Sroger	else {
27351694Sroger		tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 );
27451694Sroger		if ( muteState == FALSE )
27551694Sroger			set_audio( bktr, AUDIO_UNMUTE );
27651694Sroger	}
27751694Sroger}
27851694Sroger
27951694Sroger/* address of BTSC/SAP decoder chip */
28051694Sroger#define TDA9850_WADDR           0xb6
28151694Sroger#define TDA9850_RADDR           0xb7
28251694Sroger
28351694Sroger
28451694Sroger/* registers in the TDA9850 BTSC/dbx chip */
28551694Sroger#define CON1ADDR                0x04
28651694Sroger#define CON2ADDR                0x05
28751694Sroger#define CON3ADDR                0x06
28851694Sroger#define CON4ADDR                0x07
28951694Sroger#define ALI1ADDR                0x08
29051694Sroger#define ALI2ADDR                0x09
29151694Sroger#define ALI3ADDR                0x0a
29251694Sroger
29351694Sroger/*
29451694Sroger * initialise the dbx chip
29551694Sroger * taken from the Linux bttv driver TDA9850 initialisation code
29651694Sroger */
29751694Srogervoid
29851694Srogerinit_BTSC( bktr_ptr_t bktr )
29951694Sroger{
30051694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON1ADDR, 0x08); /* noise threshold st */
30151694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON2ADDR, 0x08); /* noise threshold sap */
30251694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON3ADDR, 0x40); /* stereo mode */
30351694Sroger    i2cWrite(bktr, TDA9850_WADDR, CON4ADDR, 0x07); /* 0 dB input gain? */
30451694Sroger    i2cWrite(bktr, TDA9850_WADDR, ALI1ADDR, 0x10); /* wideband alignment? */
30551694Sroger    i2cWrite(bktr, TDA9850_WADDR, ALI2ADDR, 0x10); /* spectral alignment? */
30651694Sroger    i2cWrite(bktr, TDA9850_WADDR, ALI3ADDR, 0x03);
30751694Sroger}
30851694Sroger
30951694Sroger/*
31051694Sroger * setup the dbx chip
31151694Sroger * XXX FIXME: alot of work to be done here, this merely unmutes it.
31251694Sroger */
31351694Srogerint
31451694Srogerset_BTSC( bktr_ptr_t bktr, int control )
31551694Sroger{
31651694Sroger	return( i2cWrite( bktr, TDA9850_WADDR, CON3ADDR, control ) );
31751694Sroger}
31851694Sroger
31951694Sroger/*
320110237Sorion * CARD_GV_BCTV2 specific functions.
32151694Sroger */
32251694Sroger
323110237Sorion#define BCTV2_AUDIO_MAIN              0x10    /* main audio program */
324110237Sorion#define BCTV2_AUDIO_SUB               0x20    /* sub audio program */
325110237Sorion#define BCTV2_AUDIO_BOTH              0x30    /* main(L) + sub(R) program */
32651694Sroger
327110237Sorion#define BCTV2_GPIO_REG0          1
328110237Sorion#define BCTV2_GPIO_REG1          3
32951694Sroger
330110237Sorion#define BCTV2_GR0_AUDIO_MODE     3
331110237Sorion#define BCTV2_GR0_AUDIO_MAIN     0       /* main program */
332110237Sorion#define BCTV2_GR0_AUDIO_SUB      3       /* sub program */
333110237Sorion#define BCTV2_GR0_AUDIO_BOTH     1       /* main(L) + sub(R) */
334110237Sorion#define BCTV2_GR0_AUDIO_MUTE     4       /* audio mute */
335110237Sorion#define BCTV2_GR0_AUDIO_MONO     8       /* force mono */
33651694Sroger
33751694Srogervoid
338110237Sorionset_bctv2_audio( bktr_ptr_t bktr )
33951694Sroger{
34051694Sroger        int data;
34151694Sroger
34251694Sroger        switch (bktr->audio_mux_select) {
34351694Sroger        case 1:         /* external */
34451694Sroger        case 2:         /* internal */
345110237Sorion                bctv2_gpio_write(bktr, BCTV2_GPIO_REG1, 0);
34651694Sroger                break;
34751694Sroger        default:        /* tuner */
348110237Sorion                bctv2_gpio_write(bktr, BCTV2_GPIO_REG1, 1);
34951694Sroger                break;
35051694Sroger        }
35151694Sroger/*      switch (bktr->audio_sap_select) { */
352110237Sorion        switch (BCTV2_AUDIO_BOTH) {
353110237Sorion        case BCTV2_AUDIO_SUB:
354110237Sorion                data = BCTV2_GR0_AUDIO_SUB;
35551694Sroger                break;
356110237Sorion        case BCTV2_AUDIO_BOTH:
357110237Sorion                data = BCTV2_GR0_AUDIO_BOTH;
35851694Sroger                break;
359110237Sorion        case BCTV2_AUDIO_MAIN:
36051694Sroger        default:
361110237Sorion                data = BCTV2_GR0_AUDIO_MAIN;
36251694Sroger                break;
36351694Sroger        }
36451694Sroger        if (bktr->audio_mute_state == TRUE)
365110237Sorion                data |= BCTV2_GR0_AUDIO_MUTE;
36651694Sroger
367110237Sorion        bctv2_gpio_write(bktr, BCTV2_GPIO_REG0, data);
36851694Sroger
36951694Sroger        return;
37051694Sroger}
37151694Sroger
37251694Sroger/* gpio_data bit assignment */
373110237Sorion#define BCTV2_GPIO_ADDR_MASK     0x000300
374110237Sorion#define BCTV2_GPIO_WE            0x000400
375110237Sorion#define BCTV2_GPIO_OE            0x000800
376110237Sorion#define BCTV2_GPIO_VAL_MASK      0x00f000
37751694Sroger
378110237Sorion#define BCTV2_GPIO_PORT_MASK     3
379110237Sorion#define BCTV2_GPIO_ADDR_SHIFT    8
380110237Sorion#define BCTV2_GPIO_VAL_SHIFT     12
38151694Sroger
38251694Sroger/* gpio_out_en value for read/write */
383110237Sorion#define BCTV2_GPIO_OUT_RMASK     0x000f00
384110237Sorion#define BCTV2_GPIO_OUT_WMASK     0x00ff00
38551694Sroger
386110237Sorion#define BCTV2_BITS       100
38751694Sroger
38851694Srogervoid
389110237Sorionbctv2_gpio_write( bktr_ptr_t bktr, int port, int val )
39051694Sroger{
39151694Sroger        u_long data, outbits;
39251694Sroger
393110237Sorion        port &= BCTV2_GPIO_PORT_MASK;
39451694Sroger        switch (port) {
39551694Sroger        case 1:
39651694Sroger        case 3:
397110237Sorion                data = ((val << BCTV2_GPIO_VAL_SHIFT) & BCTV2_GPIO_VAL_MASK) |
398110237Sorion                       ((port << BCTV2_GPIO_ADDR_SHIFT) & BCTV2_GPIO_ADDR_MASK) |
399110237Sorion                       BCTV2_GPIO_WE | BCTV2_GPIO_OE;
400110237Sorion                outbits = BCTV2_GPIO_OUT_WMASK;
40151694Sroger                break;
40251694Sroger        default:
40351694Sroger                return;
40451694Sroger        }
40559014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
40659014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
40759014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, outbits);
408110237Sorion        DELAY(BCTV2_BITS);
409110237Sorion        OUTL(bktr, BKTR_GPIO_DATA, data & ~BCTV2_GPIO_WE);
410110237Sorion        DELAY(BCTV2_BITS);
41159014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
412110237Sorion        DELAY(BCTV2_BITS);
41359014Sroger        OUTL(bktr, BKTR_GPIO_DATA, ~0);
41459014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
41551694Sroger}
41651694Sroger
41751694Sroger/* Not yet used
41851694Srogerint
419110237Sorionbctv2_gpio_read( bktr_ptr_t bktr, int port )
42051694Sroger{
42151694Sroger        u_long data, outbits, ret;
42251694Sroger
423110237Sorion        port &= BCTV2_GPIO_PORT_MASK;
42451694Sroger        switch (port) {
42551694Sroger        case 1:
42651694Sroger        case 3:
427110237Sorion                data = ((port << BCTV2_GPIO_ADDR_SHIFT) & BCTV2_GPIO_ADDR_MASK) |
428110237Sorion                       BCTV2_GPIO_WE | BCTV2_GPIO_OE;
429110237Sorion                outbits = BCTV2_GPIO_OUT_RMASK;
43051694Sroger                break;
43151694Sroger        default:
43251694Sroger                return( -1 );
43351694Sroger        }
43459014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
43559014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
43659014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, outbits);
437110237Sorion        DELAY(BCTV2_BITS);
438110237Sorion        OUTL(bktr, BKTR_GPIO_DATA, data & ~BCTV2_GPIO_OE);
439110237Sorion        DELAY(BCTV2_BITS);
44059014Sroger        ret = INL(bktr, BKTR_GPIO_DATA);
441110237Sorion        DELAY(BCTV2_BITS);
44259014Sroger        OUTL(bktr, BKTR_GPIO_DATA, data);
443110237Sorion        DELAY(BCTV2_BITS);
44459014Sroger        OUTL(bktr, BKTR_GPIO_DATA, ~0);
44559014Sroger        OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
446110237Sorion        return( (ret & BCTV2_GPIO_VAL_MASK) >> BCTV2_GPIO_VAL_SHIFT );
44751694Sroger}
44851694Sroger*/
44951694Sroger
45051694Sroger/*
45151694Sroger * setup the MSP34xx Stereo Audio Chip
45251694Sroger * This uses the Auto Configuration Option on MSP3410D and MSP3415D chips
45351694Sroger * and DBX mode selection for MSP3430G chips.
45451694Sroger * For MSP3400C support, the full programming sequence is required and is
45551694Sroger * not yet supported.
45651694Sroger */
45751694Sroger
45851694Sroger/* Read the MSP version string */
45951694Srogervoid msp_read_id( bktr_ptr_t bktr ){
46051694Sroger    int rev1=0, rev2=0;
46152593Sroger    rev1 = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x001e);
46252593Sroger    rev2 = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x001f);
46351694Sroger
46451694Sroger    sprintf(bktr->msp_version_string, "34%02d%c-%c%d",
46551694Sroger      (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
46651694Sroger
46751694Sroger}
46851694Sroger
46951694Sroger
47059014Sroger/* Configure the MSP chip to Auto-detect the audio format.
47159014Sroger * For the MSP3430G, we use fast autodetect mode
47259014Sroger * For the MSP3410/3415 there are two schemes for this
47359014Sroger *  a) Fast autodetection - the chip is put into autodetect mode, and the function
47459014Sroger *     returns immediatly. This works in most cases and is the Default Mode.
47559014Sroger *  b) Slow mode. The function sets the MSP3410/3415 chip, then waits for feedback from
47659014Sroger *     the chip and re-programs it if needed.
47759014Sroger */
47851694Srogervoid msp_autodetect( bktr_ptr_t bktr ) {
479118819Salex
480118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER
481118819Salex
482118819Salex  /* Just wake up the (maybe) sleeping thread, it'll do everything for us */
483118819Salex  msp_wake_thread(bktr);
484118819Salex
485118819Salex#else
48659014Sroger  int auto_detect, loops;
48759014Sroger  int stereo;
48851694Sroger
48959014Sroger  /* MSP3430G - countries with mono and DBX stereo */
49051694Sroger  if (strncmp("3430G", bktr->msp_version_string, 5) == 0){
49151694Sroger
49252593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0030,0x2003);/* Enable Auto format detection */
49352593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0020);/* Standard Select Reg. = BTSC-Stereo*/
49452593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000E,0x2403);/* darned if I know */
49552593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0320);/* Source select = (St or A) */
49659014Sroger					                     /* & Ch. Matrix = St */
49752593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
49859014Sroger  }
49951694Sroger
50051694Sroger
501242692Skevlo  /* MSP3415D SPECIAL CASE Use the Tuner's Mono audio output for the MSP */
50268071Sroger  /* (for Hauppauge 44xxx card with Tuner Type 0x2a) */
50368071Sroger  else if (  ( (strncmp("3415D", bktr->msp_version_string, 5) == 0)
50468071Sroger               &&(bktr->msp_use_mono_source == 1)
50568071Sroger              )
50668071Sroger           || (bktr->slow_msp_audio == 2) ){
50768071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
50868071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000d, 0x1900); /* scart prescale */
50968071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008, 0x0220); /* SCART | STEREO */
51068071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0013, 0x0100); /* DSP In = MONO IN */
51168071Sroger  }
51268071Sroger
51368071Sroger
51459014Sroger  /* MSP3410/MSP3415 - countries with mono, stereo using 2 FM channels and NICAM */
51559014Sroger  /* FAST sound scheme */
51668071Sroger  else if (bktr->slow_msp_audio == 0) {
51752593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
51868071Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0000);/* Spkr Source = default(FM/AM) */
51952593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */
52052593Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */
52151694Sroger  }
52251694Sroger
52359014Sroger
52459014Sroger  /* MSP3410/MSP3415 - European Countries where the fast MSP3410/3415 programming fails */
52559014Sroger  /* SLOW sound scheme */
52668071Sroger  else if ( bktr->slow_msp_audio == 1) {
52759014Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
52859014Sroger    msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */
52959014Sroger
53059014Sroger    /* wait for 0.5s max for terrestrial sound autodetection */
53159014Sroger    loops = 10;
53259014Sroger    do {
53359014Sroger      DELAY(100000);
53459014Sroger      auto_detect = msp_dpl_read(bktr, bktr->msp_addr, 0x10, 0x007e);
53559014Sroger      loops++;
53659014Sroger    } while (auto_detect > 0xff && loops < 50);
53762112Sroger    if (bootverbose)printf ("%s: Result of autodetect after %dms: %d\n",
53862112Sroger			    bktr_name(bktr), loops*10, auto_detect);
53959014Sroger
54059014Sroger    /* Now set the audio baseband processing */
54159014Sroger    switch (auto_detect) {
54259014Sroger    case 0:                    /* no TV sound standard detected */
54359014Sroger      break;
54459014Sroger    case 2:                    /* M Dual FM */
54559014Sroger      break;
54659014Sroger    case 3:                    /* B/G Dual FM; German stereo */
54759014Sroger      /* Read the stereo detection value from DSP reg 0x0018 */
54859014Sroger      DELAY(20000);
54959014Sroger      stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
55062112Sroger      if (bootverbose)printf ("%s: Stereo reg 0x18 a: %d\n",
55162112Sroger			      bktr_name(bktr), stereo);
55259014Sroger      DELAY(20000);
55359014Sroger      stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
55462112Sroger      if (bootverbose)printf ("%s: Stereo reg 0x18 b: %d\n",
55562112Sroger			      bktr_name(bktr), stereo);
55659014Sroger      DELAY(20000);
55759014Sroger      stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
55862112Sroger      if (bootverbose)printf ("%s: Stereo reg 0x18 c: %d\n",
55962112Sroger			      bktr_name(bktr), stereo);
56059014Sroger      if (stereo > 0x0100 && stereo < 0x8000) { /* Seems to be stereo */
56159014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0020);/* Loudspeaker set stereo*/
56259014Sroger        /*
56359014Sroger          set spatial effect strength to 50% enlargement
56459014Sroger          set spatial effect mode b, stereo basewidth enlargment only
56559014Sroger        */
56659014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x3f28);
56759014Sroger      } else if (stereo > 0x8000) {    /* bilingual mode */
56862112Sroger        if (bootverbose) printf ("%s: Bilingual mode detected\n",
56962112Sroger				 bktr_name(bktr));
57059014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0000);/* Loudspeaker */
57159014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x0000);/* all spatial effects off */
57259014Sroger       } else {                 /* must be mono */
57359014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0030);/* Loudspeaker */
57459014Sroger        /*
57559014Sroger          set spatial effect strength to 50% enlargement
57659014Sroger          set spatial effect mode a, stereo basewidth enlargment
57759014Sroger          and pseudo stereo effect with automatic high-pass filter
57859014Sroger        */
57959014Sroger        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x3f08);
58059014Sroger      }
58159014Sroger#if 0
58259014Sroger       /* The reset value for Channel matrix mode is FM/AM and SOUNDA/LEFT */
58359014Sroger       /* We would like STEREO instead val: 0x0020 */
58459014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0020);/* Loudspeaker */
58559014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0009,0x0020);/* Headphone */
58659014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000a,0x0020);/* SCART1 */
58759014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0041,0x0020);/* SCART2 */
58859014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000b,0x0020);/* I2S */
58959014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000c,0x0020);/* Quasi-Peak Detector Source */
59059014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000e,0x0001);
59159014Sroger#endif
59259014Sroger      break;
59359014Sroger    case 8:                    /* B/G FM NICAM */
59459014Sroger       msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */
59559014Sroger       break;
59659014Sroger     case 9:                    /* L_AM NICAM or D/K*/
59759014Sroger     case 10:                   /* i-FM NICAM */
59859014Sroger       break;
59959014Sroger     default:
60062112Sroger       if (bootverbose) printf ("%s: Unknown autodetection result value: %d\n",
60162112Sroger				bktr_name(bktr), auto_detect);
60259014Sroger     }
60359014Sroger
60459014Sroger  }
60559014Sroger
60659014Sroger
60751694Sroger  /* uncomment the following line to enable the MSP34xx 1Khz Tone Generator */
60851694Sroger  /* turn your speaker volume down low before trying this */
60952593Sroger  /* msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0014, 0x7f40); */
610118819Salex
611118819Salex#endif /* BKTR_NEW_MSP34XX_DRIVER */
61251694Sroger}
61352593Sroger
61452593Sroger/* Read the DPL version string */
61552593Srogervoid dpl_read_id( bktr_ptr_t bktr ){
61652593Sroger    int rev1=0, rev2=0;
61752593Sroger    rev1 = msp_dpl_read(bktr, bktr->dpl_addr, 0x12, 0x001e);
61852593Sroger    rev2 = msp_dpl_read(bktr, bktr->dpl_addr, 0x12, 0x001f);
61952593Sroger
62052593Sroger    sprintf(bktr->dpl_version_string, "34%02d%c-%c%d",
62152593Sroger      ((rev2>>8)&0xff)-1, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
62252593Sroger}
62352593Sroger
62452593Sroger/* Configure the DPL chip to Auto-detect the audio format */
62552593Srogervoid dpl_autodetect( bktr_ptr_t bktr ) {
62652593Sroger
62752593Sroger    /* The following are empiric values tried from the DPL35xx data sheet */
62852593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x000c,0x0320);	/* quasi peak detector source dolby
62952593Sroger								lr 0x03xx; quasi peak detector matrix
63052593Sroger								stereo 0xXX20 */
63152593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0040,0x0060);	/* Surround decoder mode;
63252593Sroger								ADAPTIVE/3D-PANORAMA, that means two
63352593Sroger								speakers and no center speaker, all
63452593Sroger								channels L/R/C/S mixed to L and R */
63552593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0041,0x0620);	/* surround source matrix;I2S2/STEREO*/
63652593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0042,0x1F00);	/* surround delay 31ms max */
63752593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0043,0x0000);	/* automatic surround input balance */
63852593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0044,0x4000);	/* surround spatial effect 50%
63952593Sroger								recommended*/
64052593Sroger    msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0045,0x5400);	/* surround panorama effect 66%
64152593Sroger								recommended with PANORAMA mode
64252593Sroger								in 0x0040 set to panorama */
64352593Sroger}
64452593Sroger
645