2
* Purpose: Driver for ESS Solo PCI audio controller.
6
* This file is part of Open Sound System.
8
* Copyright (C) 4Front Technologies 1996-2008.
10
* This this source file is released under GPL v2 license (no other versions).
11
* See the COPYING file included in the main directory of this source
12
* distribution for the license terms and conditions.
16
#include "oss_solo_cfg.h"
19
#define ESS_VENDOR_ID 0x125d
20
#define ESS_SOLO1 0x1969
22
#define DSP_RESET (devc->sb_base + 0x6)
23
#define DSP_READ (devc->sb_base + 0xA)
24
#define DSP_WRITE (devc->sb_base + 0xC)
25
#define DSP_WRSTATUS (devc->sb_base + 0xC)
26
#define DSP_STATUS (devc->sb_base + 0xE)
27
#define DSP_STATUS16 (devc->sb_base + 0xF)
28
#define MIXER_ADDR (devc->sb_base + 0x4)
29
#define MIXER_DATA (devc->sb_base + 0x5)
30
#define OPL3_LEFT (devc->sb_base + 0x0)
31
#define OPL3_RIGHT (devc->sb_base + 0x2)
32
#define OPL3_BOTH (devc->sb_base + 0x8)
34
#define DSP_CMD_SPKON 0xD1
35
#define DSP_CMD_SPKOFF 0xD3
37
#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
38
#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | \
39
SOUND_MASK_LINE | SOUND_MASK_MIC | \
40
SOUND_MASK_CD | SOUND_MASK_VOLUME)
41
#define SOLO_RECORDING_DEVICES (SBPRO_RECORDING_DEVICES)
42
#define SOLO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER|SOUND_MASK_RECLEV|SOUND_MASK_LINE1)
50
#define RECORD_SRC 0x0C
51
#define IN_FILTER 0x0C
52
#define OUT_FILTER 0x0E
53
#define MASTER_VOL 0x22
62
static int default_levels[32] = {
63
0x5a5a, /* Master Volume */
68
0x4b4b, /* PC Speaker */
69
0x4b4b, /* Ext Line */
72
0x0000, /* Recording monitor */
74
0x4b4b, /* Recording level */
75
0x4b4b, /* Input gain */
76
0x4b4b, /* Output gain */
84
typedef struct solo_portc
86
int speed, bits, channels;
94
typedef struct solo_devc
97
oss_native_word base, ddma_base, sb_base, mpu_base;
99
int mpu_attached, fm_attached;
103
oss_mutex_t low_mutex;
104
oss_native_word last_capture_addr;
105
/* Audio parameters */
106
solo_portc portc[MAX_PORTC];
108
/* Mixer parameters */
116
solo_command (solo_devc * devc, unsigned char val)
120
for (i = 0; i < 0x10000; i++)
122
if ((INB (devc->osdev, DSP_WRSTATUS) & 0x80) == 0)
124
OUTB (devc->osdev, val, DSP_WRITE);
129
cmn_err (CE_WARN, "Command(%x) Timeout.\n", val);
134
solo_get_byte (solo_devc * devc)
138
for (i=0; i < 0x10000; i++)
139
if (INB (devc->osdev, DSP_STATUS) & 0x80)
141
return INB (devc->osdev, DSP_READ);
148
ext_read (solo_devc * devc, unsigned char reg)
151
if (!solo_command (devc, 0xc0)) /* Read register command */
154
if (!solo_command (devc, reg))
157
return solo_get_byte (devc);
161
ext_write (solo_devc * devc, unsigned char reg, unsigned char data)
163
if (!solo_command (devc, reg))
165
return solo_command (devc, data);
169
solo_getmixer (solo_devc * devc, unsigned int port)
172
oss_native_word flags;
174
MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
175
OUTB (devc->osdev, (unsigned char) (port & 0xff), MIXER_ADDR);
177
val = INB (devc->osdev, MIXER_DATA);
178
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
183
solo_setmixer (solo_devc * devc, unsigned int port, unsigned int value)
185
oss_native_word flags;
187
MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
188
OUTB (devc->osdev, (unsigned char) (port & 0xff), MIXER_ADDR);
190
OUTB (devc->osdev, (unsigned char) (value & 0xff), MIXER_DATA);
191
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
195
solo_reset (solo_devc * devc)
199
DDB (cmn_err (CE_WARN, "Entered solo_reset()\n"));
201
OUTB (devc->osdev, 3, DSP_RESET); /* Reset FIFO too */
202
INB (devc->osdev, DSP_RESET); /* Reset FIFO too */
203
OUTB (devc->osdev, 0, DSP_RESET);
206
for (loopc = 0; loopc < 0x10000; loopc++)
207
if (INB (devc->osdev, DSP_STATUS) & 0x80)
208
if (INB (devc->osdev, DSP_READ) != 0xAA)
210
DDB (cmn_err (CE_WARN, "No response to RESET\n"));
211
return 0; /* Sorry */
213
solo_command (devc, 0xc6); /* Enable extended mode */
215
ext_write (devc, 0xb9, 3); /* Demand mode - set to reserve mode */
216
solo_setmixer (devc, 0x71, 0x32); /* 4x sampling + DAC2 asynch */
219
ext_write (devc, 0xb1, (ext_read (devc, 0xb1) & 0x0F) | 0x50);
220
ext_write (devc, 0xb2, (ext_read (devc, 0xb2) & 0x0F) | 0x50);
222
DDB (cmn_err (CE_WARN, "solo_reset() OK\n"));
228
unsigned int regno:8;
229
unsigned int bitoffs:4;
230
unsigned int nbits:4;
233
typedef struct mixer_def mixer_tab[32][2];
234
typedef struct mixer_def mixer_ent;
236
#define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r) \
237
{{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}}
239
static mixer_tab solo_mix = {
240
MIX_ENT (SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4),
241
MIX_ENT (SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
242
MIX_ENT (SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
243
MIX_ENT (SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
244
MIX_ENT (SOUND_MIXER_PCM, 0x7c, 7, 4, 0x7c, 3, 4),
245
MIX_ENT (SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
246
MIX_ENT (SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
247
MIX_ENT (SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
248
MIX_ENT (SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
249
MIX_ENT (SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
250
MIX_ENT (SOUND_MIXER_ALTPCM, 0x7c, 7, 4, 0x7c, 3, 4),
251
MIX_ENT (SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
252
MIX_ENT (SOUND_MIXER_IGAIN, 0x68, 7, 4, 0x68, 3, 4),
253
MIX_ENT (SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
254
MIX_ENT (SOUND_MIXER_LINE1, 0x6d, 7, 4, 0x6d, 3, 4),
255
MIX_ENT (SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
256
MIX_ENT (SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
261
change_bits (solo_devc * devc, unsigned char *regval, int dev, int chn,
267
mask = (1 << solo_mix[dev][chn].nbits) - 1;
268
newval = (int) ((newval * mask) + 50) / 100; /* Scale */
270
shift = solo_mix[dev][chn].bitoffs - solo_mix[dev][LEFT_CHN].nbits + 1;
272
*regval &= ~(mask << shift); /* Mask out previous value */
273
*regval |= (newval & mask) << shift; /* Set the new value */
278
ess_set_reclev (solo_devc * devc, int dev, int left, int right)
282
b = (((15 * right) / 100) << 4) | (((15 * left) / 100));
284
ext_write (devc, 0xb4, b); /* Change input volume control */
285
devc->levels[dev] = left | (right << 8);
286
return left | (right << 8);
290
ess_set_altpcm (solo_devc * devc, int dev, int left, int right)
294
b = (((15 * right) / 100) << 4) | (((15 * left) / 100));
295
solo_setmixer (devc, 0x7C, b); /* Change dac2 volume control */
296
devc->levels[dev] = left | (right << 8);
297
return left | (right << 8);
301
static int set_recmask (solo_devc * devc, int mask);
304
solo_mixer_set (solo_devc * devc, int dev, int value)
306
int left = value & 0x000000ff;
307
int right = (value & 0x0000ff00) >> 8;
318
if (dev == SOUND_MIXER_RECLEV)
319
return ess_set_reclev (devc, dev, left, right);
320
if (dev == SOUND_MIXER_ALTPCM)
321
return ess_set_altpcm (devc, dev, left, right);
327
if (!(SOLO_MIXER_DEVICES & (1 << dev))) /*
332
regoffs = solo_mix[dev][LEFT_CHN].regno;
337
val = solo_getmixer (devc, regoffs);
338
change_bits (devc, &val, dev, LEFT_CHN, left);
340
devc->levels[dev] = left | (left << 8);
342
if (solo_mix[dev][RIGHT_CHN].regno != regoffs) /*
346
solo_setmixer (devc, regoffs, val); /*
349
regoffs = solo_mix[dev][RIGHT_CHN].regno;
352
return left | (left << 8); /*
353
* Just left channel present
356
val = solo_getmixer (devc, regoffs); /*
361
change_bits (devc, &val, dev, RIGHT_CHN, right);
363
solo_setmixer (devc, regoffs, val);
365
devc->levels[dev] = left | (right << 8);
366
return left | (right << 8);
371
solo_mixer_ioctl (int dev, int audiodev, unsigned int cmd, ioctl_arg arg)
373
solo_devc *devc = mixer_devs[dev]->devc;
376
if (cmd == SOUND_MIXER_PRIVATE1)
379
if (val != 0 && val != 1)
384
cmn_err (CE_WARN, "turning on 26db mic boost\n");
385
ext_write (devc, 0xa9, ext_read (devc, 0xa9) | 0xC);
389
cmn_err (CE_WARN, "turning off 26db mic boost\n");
390
ext_write (devc, 0xa9, ext_read (devc, 0xa9) & ~0x4);
396
if (((cmd >> 8) & 0xff) == 'M')
398
if (IOC_IS_OUTPUT (cmd))
401
case SOUND_MIXER_RECSRC:
403
return *arg = set_recmask (devc, val);
409
return *arg = solo_mixer_set (devc, cmd & 0xff, val);
415
case SOUND_MIXER_RECSRC:
416
return *arg = devc->recmask;
419
case SOUND_MIXER_DEVMASK:
420
return *arg = SOLO_MIXER_DEVICES;
423
case SOUND_MIXER_STEREODEVS:
424
return *arg = SOLO_MIXER_DEVICES &
425
~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
428
case SOUND_MIXER_RECMASK:
429
return *arg = SOLO_RECORDING_DEVICES;
432
case SOUND_MIXER_CAPS:
433
return *arg = SOUND_CAP_EXCL_INPUT;
437
return *arg = devc->levels[cmd & 0x1f];
445
set_recsrc (solo_devc * devc, int src)
447
solo_setmixer (devc, RECORD_SRC,
448
(solo_getmixer (devc, RECORD_SRC) & ~7) | (src & 0x7));
452
set_recmask (solo_devc * devc, int mask)
454
int devmask = mask & SOLO_RECORDING_DEVICES;
456
if (devmask != SOUND_MASK_MIC &&
457
devmask != SOUND_MASK_LINE && devmask != SOUND_MASK_CD)
459
* More than one devices selected.
460
* Drop the previous selection
462
devmask &= ~devc->recmask;
465
if (devmask != SOUND_MASK_MIC &&
466
devmask != SOUND_MASK_LINE && devmask != SOUND_MASK_CD)
468
* More than one devices selected.
471
devmask = SOUND_MASK_MIC;
475
if (devmask ^ devc->recmask) /*
476
* Input source changed
483
set_recsrc (devc, 0);
486
case SOUND_MASK_LINE:
487
set_recsrc (devc, 6);
491
set_recsrc (devc, 2);
495
set_recsrc (devc, 0);
499
devc->recmask = devmask;
500
return devc->recmask;
504
solo_mixer_reset (solo_devc * devc)
509
sprintf (name, "SOLO");
511
devc->levels = load_mixer_volumes (name, default_levels, 1);
514
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
515
solo_mixer_set (devc, i, devc->levels[i]);
517
set_recmask (devc, SOUND_MASK_MIC);
520
static mixer_driver_t solo_mixer_driver = {
525
solointr (oss_device_t * osdev)
527
solo_devc *devc = (solo_devc *) osdev->devc;
531
oss_native_word flags;
533
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
534
status = INB (devc->osdev, devc->base + 7);
536
for (i = 0; i < MAX_PORTC; i++)
538
if (status & 0x10) /* ESS Native Mode */
541
solo_portc *portc = &devc->portc[i];
544
instat = INB (devc->osdev, DSP_STATUS); /* Ack the interrupt */
545
if (portc->trigger_bits & PCM_ENABLE_INPUT)
546
oss_audio_inputintr (portc->audiodev, 1);
549
if (status & 0x20) /* ESS DAC2 Mode */
551
solo_portc *portc = &devc->portc[i];
554
if (portc->trigger_bits & PCM_ENABLE_OUTPUT)
555
oss_audio_outputintr (portc->audiodev, 1);
556
solo_setmixer (devc, 0x7A, solo_getmixer (devc, 0x7A) & 0x47);
560
if (status & 0x80) /* MPU interrupt */
563
/* uart401intr (INT_HANDLER_CALL (devc->irq)); *//* UART401 interrupt */
565
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
571
solo_audio_set_rate (int dev, int arg)
573
solo_portc *portc = audio_engines[dev]->portc;
587
solo_audio_set_channels (int dev, short arg)
589
solo_portc *portc = audio_engines[dev]->portc;
591
if ((arg != 1) && (arg != 2))
592
return portc->channels;
593
portc->channels = arg;
595
return portc->channels;
599
solo_audio_set_format (int dev, unsigned int arg)
601
solo_portc *portc = audio_engines[dev]->portc;
606
if (!(arg & (AFMT_U8 | AFMT_S16_LE)))
615
solo_audio_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
620
static void solo_audio_trigger (int dev, int state);
623
solo_audio_reset (int dev)
625
solo_audio_trigger (dev, 0);
629
solo_audio_reset_input (int dev)
631
solo_portc *portc = audio_engines[dev]->portc;
632
solo_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_INPUT);
636
solo_audio_reset_output (int dev)
638
solo_portc *portc = audio_engines[dev]->portc;
639
solo_audio_trigger (dev, portc->trigger_bits & ~PCM_ENABLE_OUTPUT);
644
solo_audio_open (int dev, int mode, int open_flags)
646
oss_native_word flags;
647
solo_portc *portc = audio_engines[dev]->portc;
648
solo_devc *devc = audio_engines[dev]->devc;
650
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
651
if (portc->open_mode)
653
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
656
portc->open_mode = mode;
657
portc->audio_enabled = ~mode;
658
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
664
solo_audio_close (int dev, int mode)
666
solo_portc *portc = audio_engines[dev]->portc;
668
solo_audio_reset (dev);
669
portc->open_mode = 0;
670
portc->audio_enabled &= ~mode;
675
solo_audio_output_block (int dev, oss_native_word buf, int count,
676
int fragsize, int intrflag)
678
solo_portc *portc = audio_engines[dev]->portc;
680
portc->audio_enabled |= PCM_ENABLE_OUTPUT;
681
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
687
solo_audio_start_input (int dev, oss_native_word buf, int count,
688
int fragsize, int intrflag)
690
solo_portc *portc = audio_engines[dev]->portc;
692
portc->audio_enabled |= PCM_ENABLE_INPUT;
693
portc->trigger_bits &= ~PCM_ENABLE_INPUT;
697
solo_audio_trigger (int dev, int state)
699
oss_native_word flags;
700
solo_portc *portc = audio_engines[dev]->portc;
701
solo_devc *devc = audio_engines[dev]->devc;
703
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
704
if (portc->open_mode & OPEN_WRITE)
706
if (state & PCM_ENABLE_OUTPUT)
708
if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
709
!(portc->trigger_bits & PCM_ENABLE_OUTPUT))
711
solo_setmixer (devc, 0x78, 0x92); /* stablilze fifos */
713
solo_setmixer (devc, 0x78, 0x93); /* Go */
714
OUTB (devc->osdev, 0x0A, devc->base + 6); /*unmask dac2 intr */
715
portc->trigger_bits |= PCM_ENABLE_OUTPUT;
720
if ((portc->audio_enabled & PCM_ENABLE_OUTPUT) &&
721
(portc->trigger_bits & PCM_ENABLE_OUTPUT))
723
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
724
portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
725
solo_setmixer (devc, 0x78, 0); /* stop the audio dac2 dma */
730
if (portc->open_mode & OPEN_READ)
732
if (state & PCM_ENABLE_INPUT)
734
if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
735
!(portc->trigger_bits & PCM_ENABLE_INPUT))
737
ext_write (devc, 0xb8, 0x0f); /* Go */
738
OUTB (devc->osdev, 0x00, devc->ddma_base + 0x0f); /*start dma*/
739
portc->trigger_bits |= PCM_ENABLE_INPUT;
744
if ((portc->audio_enabled & PCM_ENABLE_INPUT) &&
745
(portc->trigger_bits & PCM_ENABLE_INPUT))
747
portc->trigger_bits &= ~PCM_ENABLE_INPUT;
748
portc->audio_enabled &= ~PCM_ENABLE_INPUT;
749
ext_write (devc, 0xb8, 0x00); /* stop */
753
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
757
ext_speed (int dev, int direction)
759
solo_devc *devc = audio_engines[dev]->devc;
760
solo_portc *portc = audio_engines[dev]->portc;
761
int divider, div, filter;
763
int speed, s0, s1, use0;
765
unsigned char t0, t1;
767
/* rate = source / (256 - divisor) */
768
/* divisor = 256 - (source / rate) */
769
speed = portc->speed;
771
t0 = 128 - (793800 / speed);
772
s0 = 793800 / (128 - t0);
774
t1 = 128 - (768000 / speed);
775
s1 = 768000 / (128 - t1);
785
use0 = (dif0 < dif1) ? 1 : 0;
799
* Set filter divider register
801
filter = (rate * 8 * 82) / 20; /* 80% of the rate */
802
divider = 256 - 7160000 / (filter);
805
ext_write (devc, 0xa1, div);
806
ext_write (devc, 0xa2, divider);
810
solo_setmixer (devc, 0x70, div);
811
solo_setmixer (devc, 0x72, divider);
817
solo_audio_prepare_for_input (int dev, int bsize, int bcount)
819
solo_devc *devc = audio_engines[dev]->devc;
820
solo_portc *portc = audio_engines[dev]->portc;
821
oss_native_word flags;
822
unsigned int left, right, reclev;
823
dmap_t *dmap = audio_engines[dev]->dmap_in;
826
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
827
OUTB (devc->osdev, 2, DSP_RESET); /* Reset FIFO too */
828
INB (devc->osdev, DSP_RESET); /* Reset FIFO too */
829
OUTB (devc->osdev, 0, DSP_RESET);
835
ext_write (devc, 0xa8, (ext_read (devc, 0xa8) & ~0x3) | (3 - portc->channels)); /* Mono/stereo */
837
solo_command (devc, DSP_CMD_SPKOFF);
839
if (portc->channels == 1)
841
if (portc->bits == AFMT_U8)
843
ext_write (devc, 0xb7, 0x51);
844
ext_write (devc, 0xb7, 0xd0);
848
ext_write (devc, 0xb7, 0x71);
849
ext_write (devc, 0xb7, 0xf4);
854
if (portc->bits == AFMT_U8)
856
ext_write (devc, 0xb7, 0x51);
857
ext_write (devc, 0xb7, 0x98);
860
{ /* 16 bit stereo */
861
ext_write (devc, 0xb7, 0x71);
862
ext_write (devc, 0xb7, 0xbc);
867
* reset the 0xb4 register to the stored value of RECLEV - for some
868
* reason it gets reset when you enter ESS Extension mode.
870
left = devc->levels[SOUND_MIXER_RECLEV] & 0xff;
871
right = (devc->levels[SOUND_MIXER_RECLEV] >> 8) & 0xff;
872
reclev = (((15 * right) / 100) << 4) | (((15 * left) / 100));
873
ext_write (devc, 0xb4, reclev);
875
OUTB (devc->osdev, 0xc4, devc->ddma_base + 0x08);
876
OUTB (devc->osdev, 0xff, devc->ddma_base + 0x0d); /* clear DMA */
877
OUTB (devc->osdev, 0x01, devc->ddma_base + 0x0f); /* stop DMA */
878
OUTB (devc->osdev, 0x14, devc->ddma_base + 0x0b); /*Demand/Single Mode */
880
OUTL (devc->osdev, dmap->dmabuf_phys, devc->ddma_base + 0x00);
881
OUTW (devc->osdev, dmap->bytes_in_use, devc->ddma_base + 0x04);
883
c = -(dmap->fragment_size);
884
/* Reload DMA Count */
885
ext_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
886
ext_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
888
portc->audio_enabled &= ~PCM_ENABLE_INPUT;
889
portc->trigger_bits &= ~PCM_ENABLE_INPUT;
890
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
896
solo_audio_prepare_for_output (int dev, int bsize, int bcount)
898
solo_devc *devc = audio_engines[dev]->devc;
899
solo_portc *portc = audio_engines[dev]->portc;
900
oss_native_word flags;
901
dmap_t *dmap = audio_engines[dev]->dmap_out;
905
MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
906
OUTB (devc->osdev, 2, DSP_RESET); /* Reset FIFO too */
907
INB (devc->osdev, DSP_RESET);
908
OUTB (devc->osdev, 0, DSP_RESET);
910
if (portc->channels == 1)
912
if (portc->bits == AFMT_U8)
913
solo_setmixer (devc, 0x7A, 0x40 | 0x00); /*8bit mono unsigned */
915
solo_setmixer (devc, 0x7A, 0x40 | 0x05); /*16bit mono signed */
919
if (portc->bits == AFMT_U8)
920
solo_setmixer (devc, 0x7A, 0x40 | 0x02); /*8bit stereo unsigned */
922
solo_setmixer (devc, 0x7A, 0x40 | 0x07); /*16bit stereo signed */
925
OUTL (devc->osdev, dmap->dmabuf_phys, devc->base + 0);
926
OUTW (devc->osdev, dmap->bytes_in_use, devc->base + 4);
928
OUTB (devc->osdev, 0x0, devc->base + 6); /* disable the DMA mask */
930
c = -(dmap->fragment_size>>1);
931
solo_setmixer (devc, 0x74, (unsigned char) ((unsigned short) c & 0xff));
932
solo_setmixer (devc, 0x76, (unsigned char) (((unsigned short) c >> 8) & 0xff));
933
portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
934
portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
935
MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
940
solo_get_buffer_pointer (int dev, dmap_t * dmap, int direction)
942
solo_devc *devc = audio_engines[dev]->devc;
943
oss_native_word flags;
944
oss_native_word ptr=0;
946
MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
947
if (direction == PCM_ENABLE_OUTPUT)
949
ptr = dmap->bytes_in_use - INW(devc->osdev, devc->base + 4);
952
if (direction == PCM_ENABLE_INPUT)
957
ptr = INL(devc->osdev, devc->ddma_base + 0x00);
958
count = INL(devc->osdev, devc->ddma_base + 0x04);
960
diff = dmap->dmabuf_phys + dmap->bytes_in_use - ptr - count;
962
if (ptr < dmap->dmabuf_phys ||
963
ptr >= dmap->dmabuf_phys + dmap->bytes_in_use)
965
ptr = devc->last_capture_addr; /* use prev value */
967
devc->last_capture_addr = ptr; /* save it */
969
ptr -= dmap->dmabuf_phys;
972
MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
977
static audiodrv_t solo_audio_driver = {
980
solo_audio_output_block,
981
solo_audio_start_input,
983
solo_audio_prepare_for_input,
984
solo_audio_prepare_for_output,
988
solo_audio_reset_input,
989
solo_audio_reset_output,
992
solo_audio_set_format,
993
solo_audio_set_channels,
998
NULL, /* solo_alloc_buffer, */
999
NULL, /* solo_free_buffer, */
1002
solo_get_buffer_pointer
1006
init_solo (solo_devc * devc)
1012
devc->mpu_attached = devc->fm_attached = 0;
1015
* Initialize and attach the legacy devices
1018
if (!solo_reset (devc))
1020
cmn_err (CE_WARN, "Reset command failed\n");
1024
/* setup mixer regs */
1025
solo_setmixer (devc, 0x7d, 0x0c);
1026
OUTB (devc->osdev, 0xf0, devc->base + 7);
1027
OUTB (devc->osdev, 0x00, devc->ddma_base + 0x0f);
1029
if ((my_mixer = oss_install_mixer (OSS_MIXER_DRIVER_VERSION,
1034
sizeof (mixer_driver_t), devc)) < 0)
1038
solo_mixer_reset (devc);
1040
for (i = 0; i < MAX_PORTC; i++)
1043
solo_portc *portc = &devc->portc[i];
1044
int caps = ADEV_AUTOMODE;
1045
strcpy (tmp_name, devc->chip_name);
1049
strcpy (tmp_name, devc->chip_name);
1050
caps |= ADEV_DUPLEX;
1054
caps |= ADEV_DUPLEX | ADEV_SHADOW;
1057
if ((adev = oss_install_audiodev (OSS_AUDIO_DRIVER_VERSION,
1062
sizeof (audiodrv_t),
1064
AFMT_U8 | AFMT_S16_LE, devc, -1)) < 0)
1073
audio_engines[adev]->portc = portc;
1074
audio_engines[adev]->rate_source = first_dev;
1075
audio_engines[adev]->mixer_dev = my_mixer;
1076
audio_engines[adev]->min_rate = 8000;
1077
audio_engines[adev]->max_rate = 48000;
1078
audio_engines[adev]->dmabuf_maxaddr = MEMLIMIT_ISA;
1079
audio_engines[adev]->dmabuf_alloc_flags |= DMABUF_SIZE_16BITS;
1080
audio_engines[adev]->caps |= PCM_CAP_FREERATE;
1081
portc->open_mode = 0;
1082
portc->audiodev = adev;
1083
portc->audio_enabled = 0;
1084
#ifdef CONFIG_OSS_VMIX
1086
vmix_attach_audiodev(devc->osdev, adev, -1, 0);
1094
oss_solo_attach (oss_device_t * osdev)
1097
unsigned char pci_irq_line, pci_revision;
1098
unsigned short pci_command, vendor, device;
1099
unsigned int pci_ioaddr0, pci_ioaddr1, pci_ioaddr2, pci_ioaddr3;
1102
DDB (cmn_err (CE_WARN, "Entered ESS Solo probe routine\n"));
1104
pci_read_config_word (osdev, PCI_VENDOR_ID, &vendor);
1105
pci_read_config_word (osdev, PCI_DEVICE_ID, &device);
1107
if (vendor != ESS_VENDOR_ID || device != ESS_SOLO1)
1110
pci_read_config_byte (osdev, PCI_REVISION_ID, &pci_revision);
1111
pci_read_config_word (osdev, PCI_COMMAND, &pci_command);
1112
pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line);
1113
pci_read_config_dword (osdev, PCI_BASE_ADDRESS_0, &pci_ioaddr0);
1114
pci_read_config_dword (osdev, PCI_BASE_ADDRESS_1, &pci_ioaddr1);
1115
pci_read_config_dword (osdev, PCI_BASE_ADDRESS_2, &pci_ioaddr2);
1116
pci_read_config_dword (osdev, PCI_BASE_ADDRESS_3, &pci_ioaddr3);
1118
if (pci_ioaddr0 == 0)
1120
cmn_err (CE_WARN, "I/O address not assigned by BIOS.\n");
1124
if (pci_irq_line == 0)
1126
cmn_err (CE_WARN, "IRQ not assigned by BIOS (%d).\n", pci_irq_line);
1130
if ((devc = PMALLOC (osdev, sizeof (*devc))) == NULL)
1132
cmn_err (CE_WARN, "Out of memory\n");
1136
devc->osdev = osdev;
1138
devc->irq = pci_irq_line;
1139
devc->chip_name = "ESS Solo-1";
1141
devc->base = MAP_PCI_IOADDR (devc->osdev, 0, pci_ioaddr0);
1142
/* Remove I/O space marker in bit 0. */
1145
pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
1146
pci_write_config_word (osdev, PCI_COMMAND, pci_command);
1148
MUTEX_INIT (devc->osdev, devc->mutex, MH_DRV);
1149
MUTEX_INIT (devc->osdev, devc->low_mutex, MH_DRV + 1);
1151
oss_register_device (osdev, devc->chip_name);
1153
if (oss_register_interrupts (devc->osdev, 0, solointr, NULL) < 0)
1155
cmn_err (CE_WARN, "Can't allocate IRQ%d\n", pci_irq_line);
1160
/* Read the VCBase register */
1161
if (pci_ioaddr2 == 0)
1163
cmn_err (CE_WARN, "DMA I/O base not set\n");
1166
/* Copy it's contents to the DDMA register */
1167
pci_write_config_dword (osdev, 0x60, pci_ioaddr2 | 0x1); /* enabled DDMA */
1168
devc->ddma_base = MAP_PCI_IOADDR (devc->osdev, 2, pci_ioaddr2);
1169
devc->ddma_base &= ~0x3;
1171
/* Init other SB base registers */
1172
if (pci_ioaddr1 == 0)
1174
cmn_err (CE_WARN, "SB I/O base not set\n");
1177
devc->sb_base = MAP_PCI_IOADDR (devc->osdev, 1, pci_ioaddr1);
1178
devc->sb_base &= ~0x3;
1181
/* Init MPU base register */
1182
if (pci_ioaddr3 == 0)
1184
cmn_err (CE_WARN, "MPU I/O base not set\n");
1187
devc->mpu_base = MAP_PCI_IOADDR (devc->osdev, 3, pci_ioaddr3);
1188
devc->mpu_base &= ~0x3;
1190
/* Setup Legacy audio register - disable legacy audio */
1191
pci_write_config_word (osdev, 0x40, 0x805f);
1193
/* Select DDMA and Disable IRQ emulation */
1194
pci_write_config_dword (osdev, 0x50, 0);
1195
pci_read_config_dword (osdev, 0x50, &pci_ioaddr0);
1196
pci_ioaddr0 &= (~(0x0700 | 0x6000));
1197
pci_write_config_dword (osdev, 0x50, pci_ioaddr0);
1199
return init_solo (devc); /* Detected */
1204
oss_solo_detach (oss_device_t * osdev)
1206
solo_devc *devc = (solo_devc *) osdev->devc;
1208
if (oss_disable_device (osdev) < 0)
1211
/* disable all interrupts */
1212
/*OUTB (devc->osdev, 0, devc->base + 7); */
1214
#ifdef OBSOLETED_STUFF
1215
if (devc->mpu_attached)
1219
oss_unregister_interrupts (devc->osdev);
1221
MUTEX_CLEANUP (devc->mutex);
1222
MUTEX_CLEANUP (devc->low_mutex);
1223
UNMAP_PCI_IOADDR (devc->osdev, 0);
1224
UNMAP_PCI_IOADDR (devc->osdev, 1);
1225
UNMAP_PCI_IOADDR (devc->osdev, 2);
1226
UNMAP_PCI_IOADDR (devc->osdev, 3);
1228
oss_unregister_device (devc->osdev);