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