2 **********************************************************************
3 * ecard.c - E-card initialization code
4 * Copyright 1999, 2000 Creative Labs, Inc.
6 **********************************************************************
8 * Date Author Summary of changes
9 * ---- ------ ------------------
10 * October 20, 1999 Bertrand Lee base code release
12 **********************************************************************
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public
25 * License along with this program; if not, write to the Free
26 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
29 **********************************************************************
35 /* Private routines */
36 static void ecard_setadcgain(struct emu10k1_card
*, struct ecard_state
*, u16
);
37 static void ecard_write(struct emu10k1_card
*, u32
);
39 /**************************************************************************
40 * @func Set the gain of the ECARD's CS3310 Trim/gain controller. The
41 * trim value consists of a 16bit value which is composed of two
42 * 8 bit gain/trim values, one for the left channel and one for the
43 * right channel. The following table maps from the Gain/Attenuation
44 * value in decibels into the corresponding bit pattern for a single
48 static void ecard_setadcgain(struct emu10k1_card
*card
, struct ecard_state
*ecard
, u16 gain
)
51 ecard
->adc_gain
= gain
;
53 /* Enable writing to the TRIM registers */
54 ecard_write(card
, ecard
->control_bits
& ~EC_TRIM_CSN
);
56 /* Do it again to insure that we meet hold time requirements */
57 ecard_write(card
, ecard
->control_bits
& ~EC_TRIM_CSN
);
59 for (currbit
= (1L << 15); currbit
; currbit
>>= 1) {
61 u32 value
= ecard
->control_bits
& ~(EC_TRIM_CSN
|EC_TRIM_SDATA
);
64 value
|= EC_TRIM_SDATA
;
67 ecard_write(card
, value
);
68 ecard_write(card
, value
| EC_TRIM_SCLK
);
69 ecard_write(card
, value
);
72 ecard_write(card
, ecard
->control_bits
);
75 /**************************************************************************
76 * @func Clock bits into the Ecard's control latch. The Ecard uses a
77 * control latch will is loaded bit-serially by toggling the Modem control
78 * lines from function 2 on the E8010. This function hides these details
79 * and presents the illusion that we are actually writing to a distinct
82 static void ecard_write(struct emu10k1_card
*card
, u32 value
)
88 spin_lock_irqsave(&card
->lock
, flags
);
90 hcvalue
= inl(card
->iobase
+ HCFG
) & ~(HOOKN_BIT
|HANDN_BIT
|PULSEN_BIT
);
92 outl(card
->iobase
+ HCFG
, hcvalue
);
94 for (count
= 0 ; count
< EC_NUM_CONTROL_BITS
; count
++) {
96 /* Set up the value */
97 data
= ((value
& 0x1) ? PULSEN_BIT
: 0);
100 outl(card
->iobase
+ HCFG
, hcvalue
| data
);
102 /* Clock the shift register */
103 outl(card
->iobase
+ HCFG
, hcvalue
| data
| HANDN_BIT
);
104 outl(card
->iobase
+ HCFG
, hcvalue
| data
);
108 outl(card
->iobase
+ HCFG
, hcvalue
| HOOKN_BIT
);
109 outl(card
->iobase
+ HCFG
, hcvalue
);
111 spin_unlock_irqrestore(&card
->lock
, flags
);
114 void __devinit
emu10k1_ecard_init(struct emu10k1_card
*card
)
117 struct ecard_state ecard
;
119 /* Set up the initial settings */
120 ecard
.mux0_setting
= EC_DEFAULT_SPDIF0_SEL
;
121 ecard
.mux1_setting
= EC_DEFAULT_SPDIF1_SEL
;
122 ecard
.mux2_setting
= 0;
123 ecard
.adc_gain
= EC_DEFAULT_ADC_GAIN
;
124 ecard
.control_bits
= EC_RAW_RUN_MODE
|
125 EC_SPDIF0_SELECT(ecard
.mux0_setting
) |
126 EC_SPDIF1_SELECT(ecard
.mux1_setting
);
129 /* Step 0: Set the codec type in the hardware control register
130 * and enable audio output */
131 hcvalue
= emu10k1_readfn0(card
, HCFG
);
132 emu10k1_writefn0(card
, HCFG
, hcvalue
| HCFG_AUDIOENABLE
| HCFG_CODECFORMAT_I2S
);
134 /* Step 1: Turn off the led and deassert TRIM_CS */
135 ecard_write(card
, EC_ADCCAL
| EC_LEDN
| EC_TRIM_CSN
);
137 /* Step 2: Calibrate the ADC and DAC */
138 ecard_write(card
, EC_DACCAL
| EC_LEDN
| EC_TRIM_CSN
);
140 /* Step 3: Wait for awhile; FIXME: Is this correct? */
142 current
->state
= TASK_INTERRUPTIBLE
;
143 schedule_timeout(HZ
);
145 /* Step 4: Switch off the DAC and ADC calibration. Note
146 * That ADC_CAL is actually an inverted signal, so we assert
147 * it here to stop calibration. */
148 ecard_write(card
, EC_ADCCAL
| EC_LEDN
| EC_TRIM_CSN
);
150 /* Step 4: Switch into run mode */
151 ecard_write(card
, ecard
.control_bits
);
153 /* Step 5: Set the analog input gain */
154 ecard_setadcgain(card
, &ecard
, ecard
.adc_gain
);