Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gina20_dsp.c
Go to the documentation of this file.
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 <[email protected]>
28 
29 ****************************************************************************/
30 
31 
32 static int set_professional_spdif(struct echoaudio *chip, char prof);
33 static int update_flags(struct echoaudio *chip);
34 
35 
36 static 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;
55  /* Since this card has no ASIC, mark it as loaded so everything
56  works OK */
57  chip->asic_loaded = TRUE;
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 
71 static int set_mixer_defaults(struct echoaudio *chip)
72 {
73  chip->professional_spdif = FALSE;
74  return init_line_levels(chip);
75 }
76 
77 
78 
79 static 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 */
98 static int load_asic(struct echoaudio *chip)
99 {
100  return 0;
101 }
102 
103 
104 
105 static 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 
150 static 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;
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);
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 !) */
182 static 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;
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 */
199 static 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 
209 static 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 |=
215  else
216  chip->comm_page->flags &=
218  chip->professional_spdif = prof;
219  return update_flags(chip);
220 }