xref: /openbmc/linux/sound/pci/echoaudio/mia_dsp.c (revision b6dcefde)
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 
32 static int set_input_clock(struct echoaudio *chip, u16 clock);
33 static int set_professional_spdif(struct echoaudio *chip, char prof);
34 static int update_flags(struct echoaudio *chip);
35 static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
36 			   int gain);
37 static int update_vmixer_level(struct echoaudio *chip);
38 
39 
40 static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
41 {
42 	int err;
43 
44 	DE_INIT(("init_hw() - Mia\n"));
45 	if (snd_BUG_ON((subdevice_id & 0xfff0) != MIA))
46 		return -ENODEV;
47 
48 	if ((err = init_dsp_comm_page(chip))) {
49 		DE_INIT(("init_hw - could not initialize DSP comm page\n"));
50 		return err;
51 	}
52 
53 	chip->device_id = device_id;
54 	chip->subdevice_id = subdevice_id;
55 	chip->bad_board = TRUE;
56 	chip->dsp_code_to_load = &card_fw[FW_MIA_DSP];
57 	/* Since this card has no ASIC, mark it as loaded so everything
58 	   works OK */
59 	chip->asic_loaded = TRUE;
60 	if ((subdevice_id & 0x0000f) == MIA_MIDI_REV)
61 		chip->has_midi = TRUE;
62 	chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
63 		ECHO_CLOCK_BIT_SPDIF;
64 
65 	if ((err = load_firmware(chip)) < 0)
66 		return err;
67 	chip->bad_board = FALSE;
68 
69 	if ((err = init_line_levels(chip)))
70 		return err;
71 
72 	DE_INIT(("init_hw done\n"));
73 	return err;
74 }
75 
76 
77 
78 static 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 Mia has no ASIC. Just do nothing */
97 static int load_asic(struct echoaudio *chip)
98 {
99 	return 0;
100 }
101 
102 
103 
104 static int set_sample_rate(struct echoaudio *chip, u32 rate)
105 {
106 	u32 control_reg;
107 
108 	switch (rate) {
109 	case 96000:
110 		control_reg = MIA_96000;
111 		break;
112 	case 88200:
113 		control_reg = MIA_88200;
114 		break;
115 	case 48000:
116 		control_reg = MIA_48000;
117 		break;
118 	case 44100:
119 		control_reg = MIA_44100;
120 		break;
121 	case 32000:
122 		control_reg = MIA_32000;
123 		break;
124 	default:
125 		DE_ACT(("set_sample_rate: %d invalid!\n", rate));
126 		return -EINVAL;
127 	}
128 
129 	/* Override the clock setting if this Mia is set to S/PDIF clock */
130 	if (chip->input_clock == ECHO_CLOCK_SPDIF)
131 		control_reg |= MIA_SPDIF;
132 
133 	/* Set the control register if it has changed */
134 	if (control_reg != le32_to_cpu(chip->comm_page->control_register)) {
135 		if (wait_handshake(chip))
136 			return -EIO;
137 
138 		chip->comm_page->sample_rate = cpu_to_le32(rate);	/* ignored by the DSP */
139 		chip->comm_page->control_register = cpu_to_le32(control_reg);
140 		chip->sample_rate = rate;
141 
142 		clear_handshake(chip);
143 		return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
144 	}
145 	return 0;
146 }
147 
148 
149 
150 static int set_input_clock(struct echoaudio *chip, u16 clock)
151 {
152 	DE_ACT(("set_input_clock(%d)\n", clock));
153 	if (snd_BUG_ON(clock != ECHO_CLOCK_INTERNAL &&
154 		       clock != ECHO_CLOCK_SPDIF))
155 		return -EINVAL;
156 
157 	chip->input_clock = clock;
158 	return set_sample_rate(chip, chip->sample_rate);
159 }
160 
161 
162 
163 /* This function routes the sound from a virtual channel to a real output */
164 static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
165 			   int gain)
166 {
167 	int index;
168 
169 	if (snd_BUG_ON(pipe >= num_pipes_out(chip) ||
170 		       output >= num_busses_out(chip)))
171 		return -EINVAL;
172 
173 	if (wait_handshake(chip))
174 		return -EIO;
175 
176 	chip->vmixer_gain[output][pipe] = gain;
177 	index = output * num_pipes_out(chip) + pipe;
178 	chip->comm_page->vmixer[index] = gain;
179 
180 	DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain));
181 	return 0;
182 }
183 
184 
185 
186 /* Tell the DSP to read and update virtual mixer levels in comm page. */
187 static int update_vmixer_level(struct echoaudio *chip)
188 {
189 	if (wait_handshake(chip))
190 		return -EIO;
191 	clear_handshake(chip);
192 	return send_vector(chip, DSP_VC_SET_VMIXER_GAIN);
193 }
194 
195 
196 
197 /* Tell the DSP to reread the flags from the comm page */
198 static int update_flags(struct echoaudio *chip)
199 {
200 	if (wait_handshake(chip))
201 		return -EIO;
202 	clear_handshake(chip);
203 	return send_vector(chip, DSP_VC_UPDATE_FLAGS);
204 }
205 
206 
207 
208 static int set_professional_spdif(struct echoaudio *chip, char prof)
209 {
210 	DE_ACT(("set_professional_spdif %d\n", prof));
211 	if (prof)
212 		chip->comm_page->flags |=
213 			cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
214 	else
215 		chip->comm_page->flags &=
216 			~cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
217 	chip->professional_spdif = prof;
218 	return update_flags(chip);
219 }
220 
221