treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156
[sfrench/cifs-2.6.git] / sound / pci / emu10k1 / emumpu401.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4  *  Routines for control of EMU10K1 MPU-401 in UART mode
5  */
6
7 #include <linux/time.h>
8 #include <linux/init.h>
9 #include <sound/core.h>
10 #include <sound/emu10k1.h>
11
12 #define EMU10K1_MIDI_MODE_INPUT         (1<<0)
13 #define EMU10K1_MIDI_MODE_OUTPUT        (1<<1)
14
15 static inline unsigned char mpu401_read(struct snd_emu10k1 *emu,
16                                         struct snd_emu10k1_midi *mpu, int idx)
17 {
18         if (emu->audigy)
19                 return (unsigned char)snd_emu10k1_ptr_read(emu, mpu->port + idx, 0);
20         else
21                 return inb(emu->port + mpu->port + idx);
22 }
23
24 static inline void mpu401_write(struct snd_emu10k1 *emu,
25                                 struct snd_emu10k1_midi *mpu, int data, int idx)
26 {
27         if (emu->audigy)
28                 snd_emu10k1_ptr_write(emu, mpu->port + idx, 0, data);
29         else
30                 outb(data, emu->port + mpu->port + idx);
31 }
32
33 #define mpu401_write_data(emu, mpu, data)       mpu401_write(emu, mpu, data, 0)
34 #define mpu401_write_cmd(emu, mpu, data)        mpu401_write(emu, mpu, data, 1)
35 #define mpu401_read_data(emu, mpu)              mpu401_read(emu, mpu, 0)
36 #define mpu401_read_stat(emu, mpu)              mpu401_read(emu, mpu, 1)
37
38 #define mpu401_input_avail(emu,mpu)     (!(mpu401_read_stat(emu,mpu) & 0x80))
39 #define mpu401_output_ready(emu,mpu)    (!(mpu401_read_stat(emu,mpu) & 0x40))
40
41 #define MPU401_RESET            0xff
42 #define MPU401_ENTER_UART       0x3f
43 #define MPU401_ACK              0xfe
44
45 static void mpu401_clear_rx(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *mpu)
46 {
47         int timeout = 100000;
48         for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--)
49                 mpu401_read_data(emu, mpu);
50 #ifdef CONFIG_SND_DEBUG
51         if (timeout <= 0)
52                 dev_err(emu->card->dev,
53                         "cmd: clear rx timeout (status = 0x%x)\n",
54                         mpu401_read_stat(emu, mpu));
55 #endif
56 }
57
58 /*
59
60  */
61
62 static void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, unsigned int status)
63 {
64         unsigned char byte;
65
66         if (midi->rmidi == NULL) {
67                 snd_emu10k1_intr_disable(emu, midi->tx_enable | midi->rx_enable);
68                 return;
69         }
70
71         spin_lock(&midi->input_lock);
72         if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) {
73                 if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
74                         mpu401_clear_rx(emu, midi);
75                 } else {
76                         byte = mpu401_read_data(emu, midi);
77                         if (midi->substream_input)
78                                 snd_rawmidi_receive(midi->substream_input, &byte, 1);
79                 }
80         }
81         spin_unlock(&midi->input_lock);
82
83         spin_lock(&midi->output_lock);
84         if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
85                 if (midi->substream_output &&
86                     snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
87                         mpu401_write_data(emu, midi, byte);
88                 } else {
89                         snd_emu10k1_intr_disable(emu, midi->tx_enable);
90                 }
91         }
92         spin_unlock(&midi->output_lock);
93 }
94
95 static void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status)
96 {
97         do_emu10k1_midi_interrupt(emu, &emu->midi, status);
98 }
99
100 static void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int status)
101 {
102         do_emu10k1_midi_interrupt(emu, &emu->midi2, status);
103 }
104
105 static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack)
106 {
107         unsigned long flags;
108         int timeout, ok;
109
110         spin_lock_irqsave(&midi->input_lock, flags);
111         mpu401_write_data(emu, midi, 0x00);
112         /* mpu401_clear_rx(emu, midi); */
113
114         mpu401_write_cmd(emu, midi, cmd);
115         if (ack) {
116                 ok = 0;
117                 timeout = 10000;
118                 while (!ok && timeout-- > 0) {
119                         if (mpu401_input_avail(emu, midi)) {
120                                 if (mpu401_read_data(emu, midi) == MPU401_ACK)
121                                         ok = 1;
122                         }
123                 }
124                 if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK)
125                         ok = 1;
126         } else {
127                 ok = 1;
128         }
129         spin_unlock_irqrestore(&midi->input_lock, flags);
130         if (!ok) {
131                 dev_err(emu->card->dev,
132                         "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n",
133                            cmd, emu->port,
134                            mpu401_read_stat(emu, midi),
135                            mpu401_read_data(emu, midi));
136                 return 1;
137         }
138         return 0;
139 }
140
141 static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream)
142 {
143         struct snd_emu10k1 *emu;
144         struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
145         unsigned long flags;
146
147         emu = midi->emu;
148         if (snd_BUG_ON(!emu))
149                 return -ENXIO;
150         spin_lock_irqsave(&midi->open_lock, flags);
151         midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT;
152         midi->substream_input = substream;
153         if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) {
154                 spin_unlock_irqrestore(&midi->open_lock, flags);
155                 if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1))
156                         goto error_out;
157                 if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1))
158                         goto error_out;
159         } else {
160                 spin_unlock_irqrestore(&midi->open_lock, flags);
161         }
162         return 0;
163
164 error_out:
165         return -EIO;
166 }
167
168 static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream)
169 {
170         struct snd_emu10k1 *emu;
171         struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
172         unsigned long flags;
173
174         emu = midi->emu;
175         if (snd_BUG_ON(!emu))
176                 return -ENXIO;
177         spin_lock_irqsave(&midi->open_lock, flags);
178         midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT;
179         midi->substream_output = substream;
180         if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
181                 spin_unlock_irqrestore(&midi->open_lock, flags);
182                 if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1))
183                         goto error_out;
184                 if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1))
185                         goto error_out;
186         } else {
187                 spin_unlock_irqrestore(&midi->open_lock, flags);
188         }
189         return 0;
190
191 error_out:
192         return -EIO;
193 }
194
195 static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream)
196 {
197         struct snd_emu10k1 *emu;
198         struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
199         unsigned long flags;
200         int err = 0;
201
202         emu = midi->emu;
203         if (snd_BUG_ON(!emu))
204                 return -ENXIO;
205         spin_lock_irqsave(&midi->open_lock, flags);
206         snd_emu10k1_intr_disable(emu, midi->rx_enable);
207         midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT;
208         midi->substream_input = NULL;
209         if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) {
210                 spin_unlock_irqrestore(&midi->open_lock, flags);
211                 err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0);
212         } else {
213                 spin_unlock_irqrestore(&midi->open_lock, flags);
214         }
215         return err;
216 }
217
218 static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream)
219 {
220         struct snd_emu10k1 *emu;
221         struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
222         unsigned long flags;
223         int err = 0;
224
225         emu = midi->emu;
226         if (snd_BUG_ON(!emu))
227                 return -ENXIO;
228         spin_lock_irqsave(&midi->open_lock, flags);
229         snd_emu10k1_intr_disable(emu, midi->tx_enable);
230         midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT;
231         midi->substream_output = NULL;
232         if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) {
233                 spin_unlock_irqrestore(&midi->open_lock, flags);
234                 err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0);
235         } else {
236                 spin_unlock_irqrestore(&midi->open_lock, flags);
237         }
238         return err;
239 }
240
241 static void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
242 {
243         struct snd_emu10k1 *emu;
244         struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
245         emu = midi->emu;
246         if (snd_BUG_ON(!emu))
247                 return;
248
249         if (up)
250                 snd_emu10k1_intr_enable(emu, midi->rx_enable);
251         else
252                 snd_emu10k1_intr_disable(emu, midi->rx_enable);
253 }
254
255 static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
256 {
257         struct snd_emu10k1 *emu;
258         struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
259         unsigned long flags;
260
261         emu = midi->emu;
262         if (snd_BUG_ON(!emu))
263                 return;
264
265         if (up) {
266                 int max = 4;
267                 unsigned char byte;
268         
269                 /* try to send some amount of bytes here before interrupts */
270                 spin_lock_irqsave(&midi->output_lock, flags);
271                 while (max > 0) {
272                         if (mpu401_output_ready(emu, midi)) {
273                                 if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) ||
274                                     snd_rawmidi_transmit(substream, &byte, 1) != 1) {
275                                         /* no more data */
276                                         spin_unlock_irqrestore(&midi->output_lock, flags);
277                                         return;
278                                 }
279                                 mpu401_write_data(emu, midi, byte);
280                                 max--;
281                         } else {
282                                 break;
283                         }
284                 }
285                 spin_unlock_irqrestore(&midi->output_lock, flags);
286                 snd_emu10k1_intr_enable(emu, midi->tx_enable);
287         } else {
288                 snd_emu10k1_intr_disable(emu, midi->tx_enable);
289         }
290 }
291
292 /*
293
294  */
295
296 static const struct snd_rawmidi_ops snd_emu10k1_midi_output =
297 {
298         .open =         snd_emu10k1_midi_output_open,
299         .close =        snd_emu10k1_midi_output_close,
300         .trigger =      snd_emu10k1_midi_output_trigger,
301 };
302
303 static const struct snd_rawmidi_ops snd_emu10k1_midi_input =
304 {
305         .open =         snd_emu10k1_midi_input_open,
306         .close =        snd_emu10k1_midi_input_close,
307         .trigger =      snd_emu10k1_midi_input_trigger,
308 };
309
310 static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
311 {
312         struct snd_emu10k1_midi *midi = rmidi->private_data;
313         midi->interrupt = NULL;
314         midi->rmidi = NULL;
315 }
316
317 static int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
318 {
319         struct snd_rawmidi *rmidi;
320         int err;
321
322         if ((err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi)) < 0)
323                 return err;
324         midi->emu = emu;
325         spin_lock_init(&midi->open_lock);
326         spin_lock_init(&midi->input_lock);
327         spin_lock_init(&midi->output_lock);
328         strcpy(rmidi->name, name);
329         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1_midi_output);
330         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1_midi_input);
331         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
332                              SNDRV_RAWMIDI_INFO_INPUT |
333                              SNDRV_RAWMIDI_INFO_DUPLEX;
334         rmidi->private_data = midi;
335         rmidi->private_free = snd_emu10k1_midi_free;
336         midi->rmidi = rmidi;
337         return 0;
338 }
339
340 int snd_emu10k1_midi(struct snd_emu10k1 *emu)
341 {
342         struct snd_emu10k1_midi *midi = &emu->midi;
343         int err;
344
345         if ((err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)")) < 0)
346                 return err;
347
348         midi->tx_enable = INTE_MIDITXENABLE;
349         midi->rx_enable = INTE_MIDIRXENABLE;
350         midi->port = MUDATA;
351         midi->ipr_tx = IPR_MIDITRANSBUFEMPTY;
352         midi->ipr_rx = IPR_MIDIRECVBUFEMPTY;
353         midi->interrupt = snd_emu10k1_midi_interrupt;
354         return 0;
355 }
356
357 int snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
358 {
359         struct snd_emu10k1_midi *midi;
360         int err;
361
362         midi = &emu->midi;
363         if ((err = emu10k1_midi_init(emu, midi, 0, "Audigy MPU-401 (UART)")) < 0)
364                 return err;
365
366         midi->tx_enable = INTE_MIDITXENABLE;
367         midi->rx_enable = INTE_MIDIRXENABLE;
368         midi->port = A_MUDATA1;
369         midi->ipr_tx = IPR_MIDITRANSBUFEMPTY;
370         midi->ipr_rx = IPR_MIDIRECVBUFEMPTY;
371         midi->interrupt = snd_emu10k1_midi_interrupt;
372
373         midi = &emu->midi2;
374         if ((err = emu10k1_midi_init(emu, midi, 1, "Audigy MPU-401 #2")) < 0)
375                 return err;
376
377         midi->tx_enable = INTE_A_MIDITXENABLE2;
378         midi->rx_enable = INTE_A_MIDIRXENABLE2;
379         midi->port = A_MUDATA2;
380         midi->ipr_tx = IPR_A_MIDITRANSBUFEMPTY2;
381         midi->ipr_rx = IPR_A_MIDIRECVBUFEMPTY2;
382         midi->interrupt = snd_emu10k1_midi_interrupt2;
383         return 0;
384 }