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	if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA20))
41		return -ENODEV;
42
43	if ((err = init_dsp_comm_page(chip))) {
44		dev_err(chip->card->dev,
45			"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	return err;
66}
67
68
69
70static int set_mixer_defaults(struct echoaudio *chip)
71{
72	chip->professional_spdif = false;
73	return init_line_levels(chip);
74}
75
76
77
78static u32 detect_input_clocks(const struct echoaudio *chip)
79{
80	u32 clocks_from_dsp, clock_bits;
81
82	/* Map the DSP clock detect bits to the generic driver clock
83	   detect bits */
84	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
85
86	clock_bits = ECHO_CLOCK_BIT_INTERNAL;
87
88	if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
89		clock_bits |= ECHO_CLOCK_BIT_SPDIF;
90
91	return clock_bits;
92}
93
94
95
96/* The Gina20 has no ASIC. Just do nothing */
97static int load_asic(struct echoaudio *chip)
98{
99	return 0;
100}
101
102
103
104static int set_sample_rate(struct echoaudio *chip, u32 rate)
105{
106	u8 clock_state, spdif_status;
107
108	if (wait_handshake(chip))
109		return -EIO;
110
111	switch (rate) {
112	case 44100:
113		clock_state = GD_CLOCK_44;
114		spdif_status = GD_SPDIF_STATUS_44;
115		break;
116	case 48000:
117		clock_state = GD_CLOCK_48;
118		spdif_status = GD_SPDIF_STATUS_48;
119		break;
120	default:
121		clock_state = GD_CLOCK_NOCHANGE;
122		spdif_status = GD_SPDIF_STATUS_NOCHANGE;
123		break;
124	}
125
126	if (chip->clock_state == clock_state)
127		clock_state = GD_CLOCK_NOCHANGE;
128	if (spdif_status == chip->spdif_status)
129		spdif_status = GD_SPDIF_STATUS_NOCHANGE;
130
131	chip->comm_page->sample_rate = cpu_to_le32(rate);
132	chip->comm_page->gd_clock_state = clock_state;
133	chip->comm_page->gd_spdif_status = spdif_status;
134	chip->comm_page->gd_resampler_state = 3;	/* magic number - should always be 3 */
135
136	/* Save the new audio state if it changed */
137	if (clock_state != GD_CLOCK_NOCHANGE)
138		chip->clock_state = clock_state;
139	if (spdif_status != GD_SPDIF_STATUS_NOCHANGE)
140		chip->spdif_status = spdif_status;
141	chip->sample_rate = rate;
142
143	clear_handshake(chip);
144	return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
145}
146
147
148
149static int set_input_clock(struct echoaudio *chip, u16 clock)
150{
151
152	switch (clock) {
153	case ECHO_CLOCK_INTERNAL:
154		/* Reset the audio state to unknown (just in case) */
155		chip->clock_state = GD_CLOCK_UNDEF;
156		chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
157		set_sample_rate(chip, chip->sample_rate);
158		chip->input_clock = clock;
159		break;
160	case ECHO_CLOCK_SPDIF:
161		chip->comm_page->gd_clock_state = GD_CLOCK_SPDIFIN;
162		chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_NOCHANGE;
163		clear_handshake(chip);
164		send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
165		chip->clock_state = GD_CLOCK_SPDIFIN;
166		chip->input_clock = clock;
167		break;
168	default:
169		return -EINVAL;
170	}
171
172	return 0;
173}
174
175
176
177/* Set input bus gain (one unit is 0.5dB !) */
178static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
179{
180	if (snd_BUG_ON(input >= num_busses_in(chip)))
181		return -EINVAL;
182
183	if (wait_handshake(chip))
184		return -EIO;
185
186	chip->input_gain[input] = gain;
187	gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
188	chip->comm_page->line_in_level[input] = gain;
189	return 0;
190}
191
192
193
194/* Tell the DSP to reread the flags from the comm page */
195static int update_flags(struct echoaudio *chip)
196{
197	if (wait_handshake(chip))
198		return -EIO;
199	clear_handshake(chip);
200	return send_vector(chip, DSP_VC_UPDATE_FLAGS);
201}
202
203
204
205static int set_professional_spdif(struct echoaudio *chip, char prof)
206{
207	if (prof)
208		chip->comm_page->flags |=
209			cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
210	else
211		chip->comm_page->flags &=
212			~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
213	chip->professional_spdif = prof;
214	return update_flags(chip);
215}
216