[BACK]Return to bktr_audio.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci / bktr

Annotation of sys/dev/pci/bktr/bktr_audio.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: bktr_audio.c,v 1.9 2007/06/11 08:10:22 robert Exp $   */
        !             2: /* $FreeBSD: src/sys/dev/bktr/bktr_audio.c,v 1.8 2000/10/31 13:09:56 roger Exp $ */
        !             3: /*
        !             4:  * This is part of the Driver for Video Capture Cards (Frame grabbers)
        !             5:  * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
        !             6:  * chipset.
        !             7:  * Copyright Roger Hardiman and Amancio Hasty.
        !             8:  *
        !             9:  * bktr_audio : This deals with controlling the audio on TV cards,
        !            10:  *                controlling the Audio Multiplexer (audio source selector).
        !            11:  *                controlling any MSP34xx stereo audio decoders.
        !            12:  *                controlling any DPL35xx dolby surround sound audio decoders.
        !            13:  *                initialising TDA98xx audio devices.
        !            14:  *
        !            15:  */
        !            16:
        !            17: /*
        !            18:  * 1. Redistributions of source code must retain the
        !            19:  * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
        !            20:  * All rights reserved.
        !            21:  *
        !            22:  * Redistribution and use in source and binary forms, with or without
        !            23:  * modification, are permitted provided that the following conditions
        !            24:  * are met:
        !            25:  * 1. Redistributions of source code must retain the above copyright
        !            26:  *    notice, this list of conditions and the following disclaimer.
        !            27:  * 2. Redistributions in binary form must reproduce the above copyright
        !            28:  *    notice, this list of conditions and the following disclaimer in the
        !            29:  *    documentation and/or other materials provided with the distribution.
        !            30:  * 3. All advertising materials mentioning features or use of this software
        !            31:  *    must display the following acknowledgement:
        !            32:  *      This product includes software developed by Amancio Hasty and
        !            33:  *      Roger Hardiman
        !            34:  * 4. The name of the author may not be used to endorse or promote products
        !            35:  *    derived from this software without specific prior written permission.
        !            36:  *
        !            37:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            38:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            39:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            40:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            41:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            42:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            43:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            44:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            45:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            46:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            47:  * POSSIBILITY OF SUCH DAMAGE.
        !            48:  */
        !            49:
        !            50: #include <sys/param.h>
        !            51: #include <sys/systm.h>
        !            52: #include <sys/kernel.h>
        !            53: #include <sys/vnode.h>
        !            54: #include <sys/proc.h>
        !            55:
        !            56: #include <dev/ic/bt8xx.h>      /* OpenBSD location of .h files */
        !            57: #include <dev/pci/bktr/bktr_reg.h>
        !            58: #include <dev/pci/bktr/bktr_core.h>
        !            59: #include <dev/pci/bktr/bktr_tuner.h>
        !            60: #include <dev/pci/bktr/bktr_card.h>
        !            61: #include <dev/pci/bktr/bktr_audio.h>
        !            62:
        !            63: /*
        !            64:  * Prototypes for the GV_BCTV specific functions.
        !            65:  */
        !            66: void    set_bctv_audio( bktr_ptr_t bktr );
        !            67: void    bctv_gpio_write( bktr_ptr_t bktr, int port, int val );
        !            68: /*int   bctv_gpio_read( bktr_ptr_t bktr, int port );*/ /* Not used */
        !            69:
        !            70:
        !            71:
        !            72: /*
        !            73:  * init_audio_devices
        !            74:  * Reset any MSP34xx or TDA98xx audio devices.
        !            75:  */
        !            76: void init_audio_devices( bktr_ptr_t bktr ) {
        !            77:
        !            78:         /* enable stereo if appropriate on TDA audio chip */
        !            79:         if ( bktr->card.dbx )
        !            80:                 init_BTSC( bktr );
        !            81:
        !            82:         /* reset the MSP34xx stereo audio chip */
        !            83:         if ( bktr->card.msp3400c )
        !            84:                 msp_dpl_reset( bktr, bktr->msp_addr );
        !            85:
        !            86:         /* reset the DPL35xx dolby audio chip */
        !            87:         if ( bktr->card.dpl3518a )
        !            88:                 msp_dpl_reset( bktr, bktr->dpl_addr );
        !            89:
        !            90: }
        !            91:
        !            92:
        !            93: /*
        !            94:  *
        !            95:  */
        !            96: #define AUDIOMUX_DISCOVER_NOT
        !            97: int
        !            98: set_audio( bktr_ptr_t bktr, int cmd )
        !            99: {
        !           100:        u_int           temp;
        !           101:        volatile u_char idx;
        !           102:
        !           103: #if defined( AUDIOMUX_DISCOVER )
        !           104:        if ( cmd >= 200 )
        !           105:                cmd -= 200;
        !           106:        else
        !           107: #endif /* AUDIOMUX_DISCOVER */
        !           108:
        !           109:        /* check for existance of audio MUXes */
        !           110:        if ( !bktr->card.audiomuxs[ 4 ] )
        !           111:                return( -1 );
        !           112:
        !           113:        switch (cmd) {
        !           114:        case AUDIO_TUNER:
        !           115: #ifdef BKTR_REVERSEMUTE
        !           116:                bktr->audio_mux_select = 3;
        !           117: #else
        !           118:                bktr->audio_mux_select = 0;
        !           119: #endif
        !           120:
        !           121:                if (bktr->reverse_mute )
        !           122:                      bktr->audio_mux_select = 0;
        !           123:                else
        !           124:                    bktr->audio_mux_select = 3;
        !           125:
        !           126:                break;
        !           127:        case AUDIO_EXTERN:
        !           128:                bktr->audio_mux_select = 1;
        !           129:                break;
        !           130:        case AUDIO_INTERN:
        !           131:                bktr->audio_mux_select = 2;
        !           132:                break;
        !           133:        case AUDIO_MUTE:
        !           134:                bktr->audio_mute_state = TRUE;  /* set mute */
        !           135:                break;
        !           136:        case AUDIO_UNMUTE:
        !           137:                bktr->audio_mute_state = FALSE; /* clear mute */
        !           138:                break;
        !           139:        default:
        !           140:                printf("%s: audio cmd error %02x\n", bktr_name(bktr),
        !           141:                       cmd);
        !           142:                return( -1 );
        !           143:        }
        !           144:
        !           145:
        !           146:        /* Most cards have a simple audio multiplexer to select the
        !           147:         * audio source. The I/O_GV card has a more advanced multiplexer
        !           148:         * and requires special handling.
        !           149:         */
        !           150:         if ( bktr->bt848_card == CARD_IO_GV ) {
        !           151:                 set_bctv_audio( bktr );
        !           152:                 return( 0 );
        !           153:        }
        !           154:
        !           155:        /* Proceed with the simpler audio multiplexer code for the majority
        !           156:         * of Bt848 cards.
        !           157:         */
        !           158:
        !           159:        /*
        !           160:         * Leave the upper bits of the GPIO port alone in case they control
        !           161:         * something like the dbx or teletext chips.  This doesn't guarantee
        !           162:         * success, but follows the rule of least astonishment.
        !           163:         */
        !           164:
        !           165:        if ( bktr->audio_mute_state == TRUE ) {
        !           166: #ifdef BKTR_REVERSEMUTE
        !           167:                idx = 0;
        !           168: #else
        !           169:                idx = 3;
        !           170: #endif
        !           171:
        !           172:                if (bktr->reverse_mute )
        !           173:                  idx  = 3;
        !           174:                else
        !           175:                  idx  = 0;
        !           176:
        !           177:        }
        !           178:        else
        !           179:                idx = bktr->audio_mux_select;
        !           180:
        !           181:
        !           182:        temp = INL(bktr, BKTR_GPIO_DATA) & ~bktr->card.gpio_mux_bits;
        !           183: #if defined( AUDIOMUX_DISCOVER )
        !           184:        OUTL(bktr, BKTR_GPIO_DATA, temp | (cmd & 0xff));
        !           185:        printf("%s: cmd: %d audio mux %x temp %x \n", bktr_name(bktr),
        !           186:                cmd, bktr->card.audiomuxs[ idx ], temp );
        !           187: #else
        !           188:        OUTL(bktr, BKTR_GPIO_DATA, temp | bktr->card.audiomuxs[ idx ]);
        !           189: #endif /* AUDIOMUX_DISCOVER */
        !           190:
        !           191:
        !           192:
        !           193:        /* Some new Hauppauge cards do not have an audio mux */
        !           194:        /* Instead we use the MSP34xx chip to select TV audio, Line-In */
        !           195:        /* FM Radio and Mute */
        !           196:        /* Examples of this are the Hauppauge 44xxx MSP34xx models */
        !           197:        /* It is ok to drive both the mux and the MSP34xx chip. */
        !           198:        /* If there is no mux, the MSP does the switching of the audio source */
        !           199:        /* If there is a mux, it does the switching of the audio source */
        !           200:
        !           201:        if ((bktr->card.msp3400c) && (bktr->audio_mux_present == 0)) {
        !           202:
        !           203:          if (bktr->audio_mute_state == TRUE ) {
        !           204:                 msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x0000); /* volume to MUTE */
        !           205:          } else {
        !           206:                 if(bktr->audio_mux_select == 0) { /* TV Tuner */
        !           207:                    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
        !           208:                    if (bktr->msp_source_selected != 0) msp_autodetect(bktr);  /* setup TV audio mode */
        !           209:                    bktr->msp_source_selected = 0;
        !           210:                 }
        !           211:                 if(bktr->audio_mux_select == 1) { /* Line In */
        !           212:                    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
        !           213:                    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000d, 0x1900); /* scart prescale */
        !           214:                    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008, 0x0220); /* SCART | STEREO */
        !           215:                    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0013, 0x0000); /* DSP In = SC1_IN_L/R */
        !           216:                    bktr->msp_source_selected = 1;
        !           217:                 }
        !           218:
        !           219:                 if(bktr->audio_mux_select == 2) { /* FM Radio */
        !           220:                    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
        !           221:                    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000d, 0x1900); /* scart prescale */
        !           222:                    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008, 0x0220); /* SCART | STEREO */
        !           223:                    msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0013, 0x0200); /* DSP In = SC2_IN_L/R */
        !           224:                    bktr->msp_source_selected = 2;
        !           225:                 }
        !           226:          }
        !           227:        }
        !           228:
        !           229:
        !           230:        return( 0 );
        !           231: }
        !           232:
        !           233:
        !           234: /*
        !           235:  *
        !           236:  */
        !           237: void
        !           238: temp_mute( bktr_ptr_t bktr, int flag )
        !           239: {
        !           240:        static int      muteState = FALSE;
        !           241:
        !           242:        if ( flag == TRUE ) {
        !           243:                muteState = bktr->audio_mute_state;
        !           244:                set_audio( bktr, AUDIO_MUTE );          /* prevent 'click' */
        !           245:        }
        !           246:        else {
        !           247:                tsleep( BKTR_SLEEP, PZERO, "tuning", hz/8 );
        !           248:                if ( muteState == FALSE )
        !           249:                        set_audio( bktr, AUDIO_UNMUTE );
        !           250:        }
        !           251: }
        !           252:
        !           253: /* address of BTSC/SAP decoder chip */
        !           254: #define TDA9850_WADDR           0xb6
        !           255: #define TDA9850_RADDR           0xb7
        !           256:
        !           257:
        !           258: /* registers in the TDA9850 BTSC/dbx chip */
        !           259: #define CON1ADDR                0x04
        !           260: #define CON2ADDR                0x05
        !           261: #define CON3ADDR                0x06
        !           262: #define CON4ADDR                0x07
        !           263: #define ALI1ADDR                0x08
        !           264: #define ALI2ADDR                0x09
        !           265: #define ALI3ADDR                0x0a
        !           266:
        !           267: /*
        !           268:  * initialise the dbx chip
        !           269:  * taken from the Linux bttv driver TDA9850 initialisation code
        !           270:  */
        !           271: void
        !           272: init_BTSC( bktr_ptr_t bktr )
        !           273: {
        !           274:     i2cWrite(bktr, TDA9850_WADDR, CON1ADDR, 0x08); /* noise threshold st */
        !           275:     i2cWrite(bktr, TDA9850_WADDR, CON2ADDR, 0x08); /* noise threshold sap */
        !           276:     i2cWrite(bktr, TDA9850_WADDR, CON3ADDR, 0x40); /* stereo mode */
        !           277:     i2cWrite(bktr, TDA9850_WADDR, CON4ADDR, 0x07); /* 0 dB input gain? */
        !           278:     i2cWrite(bktr, TDA9850_WADDR, ALI1ADDR, 0x10); /* wideband alignment? */
        !           279:     i2cWrite(bktr, TDA9850_WADDR, ALI2ADDR, 0x10); /* spectral alignment? */
        !           280:     i2cWrite(bktr, TDA9850_WADDR, ALI3ADDR, 0x03);
        !           281: }
        !           282:
        !           283: /*
        !           284:  * setup the dbx chip
        !           285:  * XXX FIXME: alot of work to be done here, this merely unmutes it.
        !           286:  */
        !           287: int
        !           288: set_BTSC( bktr_ptr_t bktr, int control )
        !           289: {
        !           290:        return( i2cWrite( bktr, TDA9850_WADDR, CON3ADDR, control ) );
        !           291: }
        !           292:
        !           293: /*
        !           294:  * CARD_GV_BCTV specific functions.
        !           295:  */
        !           296:
        !           297: #define BCTV_AUDIO_MAIN              0x10    /* main audio program */
        !           298: #define BCTV_AUDIO_SUB               0x20    /* sub audio program */
        !           299: #define BCTV_AUDIO_BOTH              0x30    /* main(L) + sub(R) program */
        !           300:
        !           301: #define BCTV_GPIO_REG0          1
        !           302: #define BCTV_GPIO_REG1          3
        !           303:
        !           304: #define BCTV_GR0_AUDIO_MODE     3
        !           305: #define BCTV_GR0_AUDIO_MAIN     0       /* main program */
        !           306: #define BCTV_GR0_AUDIO_SUB      3       /* sub program */
        !           307: #define BCTV_GR0_AUDIO_BOTH     1       /* main(L) + sub(R) */
        !           308: #define BCTV_GR0_AUDIO_MUTE     4       /* audio mute */
        !           309: #define BCTV_GR0_AUDIO_MONO     8       /* force mono */
        !           310:
        !           311: void
        !           312: set_bctv_audio( bktr_ptr_t bktr )
        !           313: {
        !           314:         int data;
        !           315:
        !           316:         switch (bktr->audio_mux_select) {
        !           317:         case 1:         /* external */
        !           318:         case 2:         /* internal */
        !           319:                 bctv_gpio_write(bktr, BCTV_GPIO_REG1, 0);
        !           320:                 break;
        !           321:         default:        /* tuner */
        !           322:                 bctv_gpio_write(bktr, BCTV_GPIO_REG1, 1);
        !           323:                 break;
        !           324:         }
        !           325: /*      switch (bktr->audio_sap_select) { */
        !           326:         switch (BCTV_AUDIO_BOTH) {
        !           327:         case BCTV_AUDIO_SUB:
        !           328:                 data = BCTV_GR0_AUDIO_SUB;
        !           329:                 break;
        !           330:         case BCTV_AUDIO_BOTH:
        !           331:                 data = BCTV_GR0_AUDIO_BOTH;
        !           332:                 break;
        !           333:         case BCTV_AUDIO_MAIN:
        !           334:         default:
        !           335:                 data = BCTV_GR0_AUDIO_MAIN;
        !           336:                 break;
        !           337:         }
        !           338:         if (bktr->audio_mute_state == TRUE)
        !           339:                 data |= BCTV_GR0_AUDIO_MUTE;
        !           340:
        !           341:         bctv_gpio_write(bktr, BCTV_GPIO_REG0, data);
        !           342:
        !           343:         return;
        !           344: }
        !           345:
        !           346: /* gpio_data bit assignment */
        !           347: #define BCTV_GPIO_ADDR_MASK     0x000300
        !           348: #define BCTV_GPIO_WE            0x000400
        !           349: #define BCTV_GPIO_OE            0x000800
        !           350: #define BCTV_GPIO_VAL_MASK      0x00f000
        !           351:
        !           352: #define BCTV_GPIO_PORT_MASK     3
        !           353: #define BCTV_GPIO_ADDR_SHIFT    8
        !           354: #define BCTV_GPIO_VAL_SHIFT     12
        !           355:
        !           356: /* gpio_out_en value for read/write */
        !           357: #define BCTV_GPIO_OUT_RMASK     0x000f00
        !           358: #define BCTV_GPIO_OUT_WMASK     0x00ff00
        !           359:
        !           360: #define BCTV_BITS       100
        !           361:
        !           362: void
        !           363: bctv_gpio_write( bktr_ptr_t bktr, int port, int val )
        !           364: {
        !           365:         u_int data, outbits;
        !           366:
        !           367:         port &= BCTV_GPIO_PORT_MASK;
        !           368:         switch (port) {
        !           369:         case 1:
        !           370:         case 3:
        !           371:                 data = ((val << BCTV_GPIO_VAL_SHIFT) & BCTV_GPIO_VAL_MASK) |
        !           372:                        ((port << BCTV_GPIO_ADDR_SHIFT) & BCTV_GPIO_ADDR_MASK) |
        !           373:                        BCTV_GPIO_WE | BCTV_GPIO_OE;
        !           374:                 outbits = BCTV_GPIO_OUT_WMASK;
        !           375:                 break;
        !           376:         default:
        !           377:                 return;
        !           378:         }
        !           379:         OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
        !           380:         OUTL(bktr, BKTR_GPIO_DATA, data);
        !           381:         OUTL(bktr, BKTR_GPIO_OUT_EN, outbits);
        !           382:         DELAY(BCTV_BITS);
        !           383:         OUTL(bktr, BKTR_GPIO_DATA, data & ~BCTV_GPIO_WE);
        !           384:         DELAY(BCTV_BITS);
        !           385:         OUTL(bktr, BKTR_GPIO_DATA, data);
        !           386:         DELAY(BCTV_BITS);
        !           387:         OUTL(bktr, BKTR_GPIO_DATA, ~0);
        !           388:         OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
        !           389: }
        !           390:
        !           391: /* Not yet used
        !           392: int
        !           393: bctv_gpio_read( bktr_ptr_t bktr, int port )
        !           394: {
        !           395:         u_int data, outbits, ret;
        !           396:
        !           397:         port &= BCTV_GPIO_PORT_MASK;
        !           398:         switch (port) {
        !           399:         case 1:
        !           400:         case 3:
        !           401:                 data = ((port << BCTV_GPIO_ADDR_SHIFT) & BCTV_GPIO_ADDR_MASK) |
        !           402:                        BCTV_GPIO_WE | BCTV_GPIO_OE;
        !           403:                 outbits = BCTV_GPIO_OUT_RMASK;
        !           404:                 break;
        !           405:         default:
        !           406:                 return( -1 );
        !           407:         }
        !           408:         OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
        !           409:         OUTL(bktr, BKTR_GPIO_DATA, data);
        !           410:         OUTL(bktr, BKTR_GPIO_OUT_EN, outbits);
        !           411:         DELAY(BCTV_BITS);
        !           412:         OUTL(bktr, BKTR_GPIO_DATA, data & ~BCTV_GPIO_OE);
        !           413:         DELAY(BCTV_BITS);
        !           414:         ret = INL(bktr, BKTR_GPIO_DATA);
        !           415:         DELAY(BCTV_BITS);
        !           416:         OUTL(bktr, BKTR_GPIO_DATA, data);
        !           417:         DELAY(BCTV_BITS);
        !           418:         OUTL(bktr, BKTR_GPIO_DATA, ~0);
        !           419:         OUTL(bktr, BKTR_GPIO_OUT_EN, 0);
        !           420:         return( (ret & BCTV_GPIO_VAL_MASK) >> BCTV_GPIO_VAL_SHIFT );
        !           421: }
        !           422: */
        !           423:
        !           424: /*
        !           425:  * setup the MSP34xx Stereo Audio Chip
        !           426:  * This uses the Auto Configuration Option on MSP3410D and MSP3415D chips
        !           427:  * and DBX mode selection for MSP3430G chips.
        !           428:  * For MSP3400C support, the full programming sequence is required and is
        !           429:  * not yet supported.
        !           430:  */
        !           431:
        !           432: /* Read the MSP version string */
        !           433: void msp_read_id( bktr_ptr_t bktr ){
        !           434:     int rev1=0, rev2=0;
        !           435:     rev1 = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x001e);
        !           436:     rev2 = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x001f);
        !           437:
        !           438:     snprintf(bktr->msp_version_string, sizeof bktr->msp_version_string,
        !           439:       "34%02d%c-%c%d", (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@',
        !           440:       rev2&0x1f);
        !           441:
        !           442: }
        !           443:
        !           444:
        !           445: /* Configure the MSP chip to Auto-detect the audio format.
        !           446:  * For the MSP3430G, we use fast autodetect mode
        !           447:  * For the MSP3410/3415 there are two schemes for this
        !           448:  *  a) Fast autodetection - the chip is put into autodetect mode, and the function
        !           449:  *     returns immediately. This works in most cases and is the Default Mode.
        !           450:  *  b) Slow mode. The function sets the MSP3410/3415 chip, then waits for feedback from
        !           451:  *     the chip and re-programs it if needed.
        !           452:  */
        !           453: void msp_autodetect( bktr_ptr_t bktr ) {
        !           454:   int auto_detect, loops;
        !           455:   int stereo;
        !           456:
        !           457:   /* MSP3430G - countries with mono and DBX stereo */
        !           458:   if (strncmp("3430G", bktr->msp_version_string, 5) == 0 ||
        !           459:       strncmp("3435G", bktr->msp_version_string, 5) == 0) {
        !           460:
        !           461:     msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0030,0x2003);/* Enable Auto format detection */
        !           462:     msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0020);/* Standard Select Reg. = BTSC-Stereo*/
        !           463:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000E,0x2403);/* darned if I know */
        !           464:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0320);/* Source select = (St or A) */
        !           465:                                                             /* & Ch. Matrix = St */
        !           466:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
        !           467:   }
        !           468:
        !           469:
        !           470:   /* MSP3415D SPECIAL CASE Use the Tuner's Mono audio output for the MSP */
        !           471:   /* (for Hauppauge 44xxx card with Tuner Type 0x2a) */
        !           472:   else if (  ( (strncmp("3415D", bktr->msp_version_string, 5) == 0)
        !           473:                &&(bktr->msp_use_mono_source == 1)
        !           474:               )
        !           475:            || (bktr->slow_msp_audio == 2) ){
        !           476:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000, 0x7300); /* 0 db volume */
        !           477:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000d, 0x1900); /* scart prescale */
        !           478:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008, 0x0220); /* SCART | STEREO */
        !           479:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0013, 0x0100); /* DSP In = MONO IN */
        !           480:   }
        !           481:
        !           482:
        !           483:   /* MSP3410/MSP3415 - countries with mono, stereo using 2 FM channels and NICAM */
        !           484:   /* FAST sound scheme */
        !           485:   else if (bktr->slow_msp_audio == 0) {
        !           486:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
        !           487:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0000);/* Spkr Source = default(FM/AM) */
        !           488:     msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */
        !           489:     msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */
        !           490:   }
        !           491:
        !           492:
        !           493:   /* MSP3410/MSP3415 - European Countries where the fast MSP3410/3415 programming fails */
        !           494:   /* SLOW sound scheme */
        !           495:   else if ( bktr->slow_msp_audio == 1) {
        !           496:     msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0000,0x7300);/* Set volume to 0db gain */
        !           497:     msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0020,0x0001);/* Enable Auto format detection */
        !           498:
        !           499:     /* wait for 0.5s max for terrestrial sound autodetection */
        !           500:     loops = 10;
        !           501:     do {
        !           502:       DELAY(100000);
        !           503:       auto_detect = msp_dpl_read(bktr, bktr->msp_addr, 0x10, 0x007e);
        !           504:       loops++;
        !           505:     } while (auto_detect > 0xff && loops < 50);
        !           506:     if (bootverbose)printf ("%s: Result of autodetect after %dms: %d\n",
        !           507:                            bktr_name(bktr), loops*10, auto_detect);
        !           508:
        !           509:     /* Now set the audio baseband processing */
        !           510:     switch (auto_detect) {
        !           511:     case 0:                    /* no TV sound standard detected */
        !           512:       break;
        !           513:     case 2:                    /* M Dual FM */
        !           514:       break;
        !           515:     case 3:                    /* B/G Dual FM; German stereo */
        !           516:       /* Read the stereo detection value from DSP reg 0x0018 */
        !           517:       DELAY(20000);
        !           518:       stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
        !           519:       if (bootverbose)printf ("%s: Stereo reg 0x18 a: %d\n",
        !           520:                              bktr_name(bktr), stereo);
        !           521:       DELAY(20000);
        !           522:       stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
        !           523:       if (bootverbose)printf ("%s: Stereo reg 0x18 b: %d\n",
        !           524:                              bktr_name(bktr), stereo);
        !           525:       DELAY(20000);
        !           526:       stereo = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x0018);
        !           527:       if (bootverbose)printf ("%s: Stereo reg 0x18 c: %d\n",
        !           528:                              bktr_name(bktr), stereo);
        !           529:       if (stereo > 0x0100 && stereo < 0x8000) { /* Seems to be stereo */
        !           530:         msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0020);/* Loudspeaker set stereo*/
        !           531:         /*
        !           532:           set spatial effect strength to 50% enlargement
        !           533:           set spatial effect mode b, stereo basewidth enlargment only
        !           534:         */
        !           535:         msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x3f28);
        !           536:       } else if (stereo > 0x8000) {    /* bilingual mode */
        !           537:         if (bootverbose) printf ("%s: Bilingual mode detected\n",
        !           538:                                 bktr_name(bktr));
        !           539:         msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0000);/* Loudspeaker */
        !           540:         msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x0000);/* all spatial effects off */
        !           541:        } else {                 /* must be mono */
        !           542:         msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0030);/* Loudspeaker */
        !           543:         /*
        !           544:           set spatial effect strength to 50% enlargement
        !           545:           set spatial effect mode a, stereo basewidth enlargment
        !           546:           and pseudo stereo effect with automatic high-pass filter
        !           547:         */
        !           548:         msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0005,0x3f08);
        !           549:       }
        !           550: #if 0
        !           551:        /* The reset value for Channel matrix mode is FM/AM and SOUNDA/LEFT */
        !           552:        /* We would like STEREO instead val: 0x0020 */
        !           553:        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0008,0x0020);/* Loudspeaker */
        !           554:        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0009,0x0020);/* Headphone */
        !           555:        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000a,0x0020);/* SCART1 */
        !           556:        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0041,0x0020);/* SCART2 */
        !           557:        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000b,0x0020);/* I2S */
        !           558:        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000c,0x0020);/* Quasi-Peak Detector Source */
        !           559:        msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x000e,0x0001);
        !           560: #endif
        !           561:       break;
        !           562:     case 8:                    /* B/G FM NICAM */
        !           563:        msp_dpl_write(bktr, bktr->msp_addr, 0x10, 0x0021,0x0001);/* Auto selection of NICAM/MONO mode */
        !           564:        break;
        !           565:      case 9:                    /* L_AM NICAM or D/K*/
        !           566:      case 10:                   /* i-FM NICAM */
        !           567:        break;
        !           568:      default:
        !           569:        if (bootverbose) printf ("%s: Unknown autodetection result value: %d\n",
        !           570:                                bktr_name(bktr), auto_detect);
        !           571:      }
        !           572:
        !           573:   }
        !           574:
        !           575:
        !           576:   /* uncomment the following line to enable the MSP34xx 1KHz Tone Generator */
        !           577:   /* turn your speaker volume down low before trying this */
        !           578:   /* msp_dpl_write(bktr, bktr->msp_addr, 0x12, 0x0014, 0x7f40); */
        !           579: }
        !           580:
        !           581: /* Read the DPL version string */
        !           582: void dpl_read_id( bktr_ptr_t bktr ){
        !           583:     int rev1=0, rev2=0;
        !           584:     rev1 = msp_dpl_read(bktr, bktr->dpl_addr, 0x12, 0x001e);
        !           585:     rev2 = msp_dpl_read(bktr, bktr->dpl_addr, 0x12, 0x001f);
        !           586:
        !           587:     snprintf(bktr->dpl_version_string, sizeof bktr->dpl_version_string,
        !           588:       "34%02d%c-%c%d", ((rev2>>8)&0xff)-1, (rev1&0xff)+'@',
        !           589:       ((rev1>>8)&0xff)+'@', rev2&0x1f);
        !           590: }
        !           591:
        !           592: /* Configure the DPL chip to Auto-detect the audio format */
        !           593: void dpl_autodetect( bktr_ptr_t bktr ) {
        !           594:
        !           595:     /* The following are empiric values tried from the DPL35xx data sheet */
        !           596:     msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x000c,0x0320);  /* quasi peak detector source dolby
        !           597:                                                                lr 0x03xx; quasi peak detector matrix
        !           598:                                                                stereo 0xXX20 */
        !           599:     msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0040,0x0060);  /* Surround decoder mode;
        !           600:                                                                ADAPTIVE/3D-PANORAMA, that means two
        !           601:                                                                speakers and no center speaker, all
        !           602:                                                                channels L/R/C/S mixed to L and R */
        !           603:     msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0041,0x0620);  /* surround source matrix;I2S2/STEREO*/
        !           604:     msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0042,0x1F00);  /* surround delay 31ms max */
        !           605:     msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0043,0x0000);  /* automatic surround input balance */
        !           606:     msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0044,0x4000);  /* surround spatial effect 50%
        !           607:                                                                recommended*/
        !           608:     msp_dpl_write(bktr, bktr->dpl_addr, 0x12, 0x0045,0x5400);  /* surround panorama effect 66%
        !           609:                                                                recommended with PANORAMA mode
        !           610:                                                                in 0x0040 set to panorama */
        !           611: }
        !           612:

CVSweb