Blame view

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