• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/sound/pci/echoaudio/
1/****************************************************************************
2
3   Copyright Echo Digital Audio Corporation (c) 1998 - 2004
4   All rights reserved
5   www.echoaudio.com
6
7   This file is part of Echo Digital Audio's generic driver library.
8
9   Echo Digital Audio's generic driver library is free software;
10   you can redistribute it and/or modify it under the terms of
11   the GNU General Public License as published by the Free Software
12   Foundation.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22   MA  02111-1307, USA.
23
24   *************************************************************************
25
26 Translation from C++ and adaptation for use in ALSA-Driver
27 were made by Giuliano Pochini <pochini@shiny.it>
28
29****************************************************************************/
30
31
32static int set_professional_spdif(struct echoaudio *chip, char prof);
33static int update_flags(struct echoaudio *chip);
34
35
36static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
37{
38	int err;
39
40	DE_INIT(("init_hw() - Gina20\n"));
41	if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA20))
42		return -ENODEV;
43
44	if ((err = init_dsp_comm_page(chip))) {
45		DE_INIT(("init_hw - could not initialize DSP comm page\n"));
46		return err;
47	}
48
49	chip->device_id = device_id;
50	chip->subdevice_id = subdevice_id;
51	chip->bad_board = TRUE;
52	chip->dsp_code_to_load = FW_GINA20_DSP;
53	chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
54	chip->clock_state = GD_CLOCK_UNDEF;
55	/* Since this card has no ASIC, mark it as loaded so everything
56	   works OK */
57	chip->asic_loaded = TRUE;
58	chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
59		ECHO_CLOCK_BIT_SPDIF;
60
61	if ((err = load_firmware(chip)) < 0)
62		return err;
63	chip->bad_board = FALSE;
64
65	DE_INIT(("init_hw done\n"));
66	return err;
67}
68
69
70
71static int set_mixer_defaults(struct echoaudio *chip)
72{
73	chip->professional_spdif = FALSE;
74	return init_line_levels(chip);
75}
76
77
78
79static u32 detect_input_clocks(const struct echoaudio *chip)
80{
81	u32 clocks_from_dsp, clock_bits;
82
83	/* Map the DSP clock detect bits to the generic driver clock
84	   detect bits */
85	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
86
87	clock_bits = ECHO_CLOCK_BIT_INTERNAL;
88
89	if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
90		clock_bits |= ECHO_CLOCK_BIT_SPDIF;
91
92	return clock_bits;
93}
94
95
96
97/* The Gina20 has no ASIC. Just do nothing */
98static int load_asic(struct echoaudio *chip)
99{
100	return 0;
101}
102
103
104
105static int set_sample_rate(struct echoaudio *chip, u32 rate)
106{
107	u8 clock_state, spdif_status;
108
109	if (wait_handshake(chip))
110		return -EIO;
111
112	switch (rate) {
113	case 44100:
114		clock_state = GD_CLOCK_44;
115		spdif_status = GD_SPDIF_STATUS_44;
116		break;
117	case 48000:
118		clock_state = GD_CLOCK_48;
119		spdif_status = GD_SPDIF_STATUS_48;
120		break;
121	default:
122		clock_state = GD_CLOCK_NOCHANGE;
123		spdif_status = GD_SPDIF_STATUS_NOCHANGE;
124		break;
125	}
126
127	if (chip->clock_state == clock_state)
128		clock_state = GD_CLOCK_NOCHANGE;
129	if (spdif_status == chip->spdif_status)
130		spdif_status = GD_SPDIF_STATUS_NOCHANGE;
131
132	chip->comm_page->sample_rate = cpu_to_le32(rate);
133	chip->comm_page->gd_clock_state = clock_state;
134	chip->comm_page->gd_spdif_status = spdif_status;
135	chip->comm_page->gd_resampler_state = 3;	/* magic number - should always be 3 */
136
137	/* Save the new audio state if it changed */
138	if (clock_state != GD_CLOCK_NOCHANGE)
139		chip->clock_state = clock_state;
140	if (spdif_status != GD_SPDIF_STATUS_NOCHANGE)
141		chip->spdif_status = spdif_status;
142	chip->sample_rate = rate;
143
144	clear_handshake(chip);
145	return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
146}
147
148
149
150static int set_input_clock(struct echoaudio *chip, u16 clock)
151{
152	DE_ACT(("set_input_clock:\n"));
153
154	switch (clock) {
155	case ECHO_CLOCK_INTERNAL:
156		/* Reset the audio state to unknown (just in case) */
157		chip->clock_state = GD_CLOCK_UNDEF;
158		chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
159		set_sample_rate(chip, chip->sample_rate);
160		chip->input_clock = clock;
161		DE_ACT(("Set Gina clock to INTERNAL\n"));
162		break;
163	case ECHO_CLOCK_SPDIF:
164		chip->comm_page->gd_clock_state = GD_CLOCK_SPDIFIN;
165		chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_NOCHANGE;
166		clear_handshake(chip);
167		send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
168		chip->clock_state = GD_CLOCK_SPDIFIN;
169		DE_ACT(("Set Gina20 clock to SPDIF\n"));
170		chip->input_clock = clock;
171		break;
172	default:
173		return -EINVAL;
174	}
175
176	return 0;
177}
178
179
180
181/* Set input bus gain (one unit is 0.5dB !) */
182static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
183{
184	if (snd_BUG_ON(input >= num_busses_in(chip)))
185		return -EINVAL;
186
187	if (wait_handshake(chip))
188		return -EIO;
189
190	chip->input_gain[input] = gain;
191	gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
192	chip->comm_page->line_in_level[input] = gain;
193	return 0;
194}
195
196
197
198/* Tell the DSP to reread the flags from the comm page */
199static int update_flags(struct echoaudio *chip)
200{
201	if (wait_handshake(chip))
202		return -EIO;
203	clear_handshake(chip);
204	return send_vector(chip, DSP_VC_UPDATE_FLAGS);
205}
206
207
208
209static int set_professional_spdif(struct echoaudio *chip, char prof)
210{
211	DE_ACT(("set_professional_spdif %d\n", prof));
212	if (prof)
213		chip->comm_page->flags |=
214			cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
215	else
216		chip->comm_page->flags &=
217			~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
218	chip->professional_spdif = prof;
219	return update_flags(chip);
220}
221