1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (c) by Daniel Kaehn <kaehndan@gmail.com
5 * Based on serial-u16550.c by Jaroslav Kysela <perex@perex.cz>,
6 * Isaku Yamahata <yamahata@private.email.ne.jp>,
7 * George Hansper <ghansper@apana.org.au>,
10 * Generic serial MIDI driver using the serdev serial bus API for hardware interaction
13 #include <linux/err.h>
14 #include <linux/init.h>
15 #include <linux/interrupt.h>
17 #include <linux/ioport.h>
18 #include <linux/module.h>
20 #include <linux/serdev.h>
21 #include <linux/serial_reg.h>
22 #include <linux/slab.h>
23 #include <linux/dev_printk.h>
25 #include <sound/core.h>
26 #include <sound/rawmidi.h>
27 #include <sound/initval.h>
29 MODULE_DESCRIPTION("Generic serial MIDI driver");
30 MODULE_LICENSE("GPL");
32 #define SERIAL_MODE_INPUT_OPEN 1
33 #define SERIAL_MODE_OUTPUT_OPEN 2
34 #define SERIAL_MODE_INPUT_TRIGGERED 3
35 #define SERIAL_MODE_OUTPUT_TRIGGERED 4
37 #define SERIAL_TX_STATE_ACTIVE 1
38 #define SERIAL_TX_STATE_WAKEUP 2
40 struct snd_serial_generic
{
41 struct serdev_device
*serdev
;
43 struct snd_card
*card
;
44 struct snd_rawmidi
*rmidi
;
45 struct snd_rawmidi_substream
*midi_output
;
46 struct snd_rawmidi_substream
*midi_input
;
48 unsigned int baudrate
;
50 unsigned long filemode
; /* open status of file */
51 struct work_struct tx_work
;
52 unsigned long tx_state
;
56 static void snd_serial_generic_tx_wakeup(struct snd_serial_generic
*drvdata
)
58 if (test_and_set_bit(SERIAL_TX_STATE_ACTIVE
, &drvdata
->tx_state
))
59 set_bit(SERIAL_TX_STATE_WAKEUP
, &drvdata
->tx_state
);
61 schedule_work(&drvdata
->tx_work
);
64 #define INTERNAL_BUF_SIZE 256
66 static void snd_serial_generic_tx_work(struct work_struct
*work
)
68 static char buf
[INTERNAL_BUF_SIZE
];
70 struct snd_serial_generic
*drvdata
= container_of(work
, struct snd_serial_generic
,
72 struct snd_rawmidi_substream
*substream
= drvdata
->midi_output
;
74 clear_bit(SERIAL_TX_STATE_WAKEUP
, &drvdata
->tx_state
);
76 while (!snd_rawmidi_transmit_empty(substream
)) {
78 if (!test_bit(SERIAL_MODE_OUTPUT_OPEN
, &drvdata
->filemode
))
81 num_bytes
= snd_rawmidi_transmit_peek(substream
, buf
, INTERNAL_BUF_SIZE
);
82 num_bytes
= serdev_device_write_buf(drvdata
->serdev
, buf
, num_bytes
);
87 snd_rawmidi_transmit_ack(substream
, num_bytes
);
89 if (!test_bit(SERIAL_TX_STATE_WAKEUP
, &drvdata
->tx_state
))
93 clear_bit(SERIAL_TX_STATE_ACTIVE
, &drvdata
->tx_state
);
96 static void snd_serial_generic_write_wakeup(struct serdev_device
*serdev
)
98 struct snd_serial_generic
*drvdata
= serdev_device_get_drvdata(serdev
);
100 snd_serial_generic_tx_wakeup(drvdata
);
103 static size_t snd_serial_generic_receive_buf(struct serdev_device
*serdev
,
104 const u8
*buf
, size_t count
)
107 struct snd_serial_generic
*drvdata
= serdev_device_get_drvdata(serdev
);
109 if (!test_bit(SERIAL_MODE_INPUT_OPEN
, &drvdata
->filemode
))
112 ret
= snd_rawmidi_receive(drvdata
->midi_input
, buf
, count
);
113 return ret
< 0 ? 0 : ret
;
116 static const struct serdev_device_ops snd_serial_generic_serdev_device_ops
= {
117 .receive_buf
= snd_serial_generic_receive_buf
,
118 .write_wakeup
= snd_serial_generic_write_wakeup
121 static int snd_serial_generic_ensure_serdev_open(struct snd_serial_generic
*drvdata
)
124 unsigned int actual_baud
;
126 if (drvdata
->filemode
)
129 dev_dbg(drvdata
->card
->dev
, "Opening serial port for card %s\n",
130 drvdata
->card
->shortname
);
131 err
= serdev_device_open(drvdata
->serdev
);
135 actual_baud
= serdev_device_set_baudrate(drvdata
->serdev
,
137 if (actual_baud
!= drvdata
->baudrate
) {
138 dev_warn(drvdata
->card
->dev
, "requested %d baud for card %s but it was actually set to %d\n",
139 drvdata
->baudrate
, drvdata
->card
->shortname
, actual_baud
);
145 static int snd_serial_generic_input_open(struct snd_rawmidi_substream
*substream
)
148 struct snd_serial_generic
*drvdata
= substream
->rmidi
->card
->private_data
;
150 dev_dbg(drvdata
->card
->dev
, "Opening input for card %s\n",
151 drvdata
->card
->shortname
);
153 err
= snd_serial_generic_ensure_serdev_open(drvdata
);
157 set_bit(SERIAL_MODE_INPUT_OPEN
, &drvdata
->filemode
);
158 drvdata
->midi_input
= substream
;
162 static int snd_serial_generic_input_close(struct snd_rawmidi_substream
*substream
)
164 struct snd_serial_generic
*drvdata
= substream
->rmidi
->card
->private_data
;
166 dev_dbg(drvdata
->card
->dev
, "Closing input for card %s\n",
167 drvdata
->card
->shortname
);
169 clear_bit(SERIAL_MODE_INPUT_OPEN
, &drvdata
->filemode
);
170 clear_bit(SERIAL_MODE_INPUT_TRIGGERED
, &drvdata
->filemode
);
172 drvdata
->midi_input
= NULL
;
174 if (!drvdata
->filemode
)
175 serdev_device_close(drvdata
->serdev
);
179 static void snd_serial_generic_input_trigger(struct snd_rawmidi_substream
*substream
,
182 struct snd_serial_generic
*drvdata
= substream
->rmidi
->card
->private_data
;
185 set_bit(SERIAL_MODE_INPUT_TRIGGERED
, &drvdata
->filemode
);
187 clear_bit(SERIAL_MODE_INPUT_TRIGGERED
, &drvdata
->filemode
);
190 static int snd_serial_generic_output_open(struct snd_rawmidi_substream
*substream
)
192 struct snd_serial_generic
*drvdata
= substream
->rmidi
->card
->private_data
;
195 dev_dbg(drvdata
->card
->dev
, "Opening output for card %s\n",
196 drvdata
->card
->shortname
);
198 err
= snd_serial_generic_ensure_serdev_open(drvdata
);
202 set_bit(SERIAL_MODE_OUTPUT_OPEN
, &drvdata
->filemode
);
204 drvdata
->midi_output
= substream
;
208 static int snd_serial_generic_output_close(struct snd_rawmidi_substream
*substream
)
210 struct snd_serial_generic
*drvdata
= substream
->rmidi
->card
->private_data
;
212 dev_dbg(drvdata
->card
->dev
, "Closing output for card %s\n",
213 drvdata
->card
->shortname
);
215 clear_bit(SERIAL_MODE_OUTPUT_OPEN
, &drvdata
->filemode
);
216 clear_bit(SERIAL_MODE_OUTPUT_TRIGGERED
, &drvdata
->filemode
);
218 if (!drvdata
->filemode
)
219 serdev_device_close(drvdata
->serdev
);
221 drvdata
->midi_output
= NULL
;
226 static void snd_serial_generic_output_trigger(struct snd_rawmidi_substream
*substream
,
229 struct snd_serial_generic
*drvdata
= substream
->rmidi
->card
->private_data
;
232 set_bit(SERIAL_MODE_OUTPUT_TRIGGERED
, &drvdata
->filemode
);
234 clear_bit(SERIAL_MODE_OUTPUT_TRIGGERED
, &drvdata
->filemode
);
237 snd_serial_generic_tx_wakeup(drvdata
);
240 static void snd_serial_generic_output_drain(struct snd_rawmidi_substream
*substream
)
242 struct snd_serial_generic
*drvdata
= substream
->rmidi
->card
->private_data
;
244 /* Flush any pending characters */
245 serdev_device_write_flush(drvdata
->serdev
);
246 cancel_work_sync(&drvdata
->tx_work
);
249 static const struct snd_rawmidi_ops snd_serial_generic_output
= {
250 .open
= snd_serial_generic_output_open
,
251 .close
= snd_serial_generic_output_close
,
252 .trigger
= snd_serial_generic_output_trigger
,
253 .drain
= snd_serial_generic_output_drain
,
256 static const struct snd_rawmidi_ops snd_serial_generic_input
= {
257 .open
= snd_serial_generic_input_open
,
258 .close
= snd_serial_generic_input_close
,
259 .trigger
= snd_serial_generic_input_trigger
,
262 static void snd_serial_generic_parse_dt(struct serdev_device
*serdev
,
263 struct snd_serial_generic
*drvdata
)
267 err
= of_property_read_u32(serdev
->dev
.of_node
, "current-speed",
270 dev_dbg(drvdata
->card
->dev
,
271 "MIDI device reading of current-speed DT param failed with error %d, using default of 38400\n",
273 drvdata
->baudrate
= 38400;
278 static void snd_serial_generic_substreams(struct snd_rawmidi_str
*stream
, int dev_num
)
280 struct snd_rawmidi_substream
*substream
;
282 list_for_each_entry(substream
, &stream
->substreams
, list
) {
283 sprintf(substream
->name
, "Serial MIDI %d-%d", dev_num
, substream
->number
);
287 static int snd_serial_generic_rmidi(struct snd_serial_generic
*drvdata
,
288 int outs
, int ins
, struct snd_rawmidi
**rmidi
)
290 struct snd_rawmidi
*rrawmidi
;
293 err
= snd_rawmidi_new(drvdata
->card
, drvdata
->card
->driver
, 0,
294 outs
, ins
, &rrawmidi
);
299 snd_rawmidi_set_ops(rrawmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
300 &snd_serial_generic_input
);
301 snd_rawmidi_set_ops(rrawmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
302 &snd_serial_generic_output
);
303 strcpy(rrawmidi
->name
, drvdata
->card
->shortname
);
305 snd_serial_generic_substreams(&rrawmidi
->streams
[SNDRV_RAWMIDI_STREAM_OUTPUT
],
306 drvdata
->serdev
->ctrl
->nr
);
307 snd_serial_generic_substreams(&rrawmidi
->streams
[SNDRV_RAWMIDI_STREAM_INPUT
],
308 drvdata
->serdev
->ctrl
->nr
);
310 rrawmidi
->info_flags
= SNDRV_RAWMIDI_INFO_OUTPUT
|
311 SNDRV_RAWMIDI_INFO_INPUT
|
312 SNDRV_RAWMIDI_INFO_DUPLEX
;
319 static int snd_serial_generic_probe(struct serdev_device
*serdev
)
321 struct snd_card
*card
;
322 struct snd_serial_generic
*drvdata
;
325 err
= snd_devm_card_new(&serdev
->dev
, SNDRV_DEFAULT_IDX1
,
326 SNDRV_DEFAULT_STR1
, THIS_MODULE
,
327 sizeof(struct snd_serial_generic
), &card
);
332 strcpy(card
->driver
, "SerialMIDI");
333 sprintf(card
->shortname
, "SerialMIDI-%d", serdev
->ctrl
->nr
);
334 sprintf(card
->longname
, "Serial MIDI device at serial%d", serdev
->ctrl
->nr
);
336 drvdata
= card
->private_data
;
338 drvdata
->serdev
= serdev
;
339 drvdata
->card
= card
;
341 snd_serial_generic_parse_dt(serdev
, drvdata
);
343 INIT_WORK(&drvdata
->tx_work
, snd_serial_generic_tx_work
);
345 err
= snd_serial_generic_rmidi(drvdata
, 1, 1, &drvdata
->rmidi
);
349 serdev_device_set_client_ops(serdev
, &snd_serial_generic_serdev_device_ops
);
350 serdev_device_set_drvdata(drvdata
->serdev
, drvdata
);
352 err
= snd_card_register(card
);
359 static const struct of_device_id snd_serial_generic_dt_ids
[] = {
360 { .compatible
= "serial-midi" },
364 MODULE_DEVICE_TABLE(of
, snd_serial_generic_dt_ids
);
366 static struct serdev_device_driver snd_serial_generic_driver
= {
368 .name
= "snd-serial-generic",
369 .of_match_table
= snd_serial_generic_dt_ids
,
371 .probe
= snd_serial_generic_probe
,
374 module_serdev_device_driver(snd_serial_generic_driver
);