1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * serial-generic.c 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>, 8 * Hannu Savolainen 9 * 10 * Generic serial MIDI driver using the serdev serial bus API for hardware interaction 11 */ 12 13 #include <linux/err.h> 14 #include <linux/init.h> 15 #include <linux/interrupt.h> 16 #include <linux/io.h> 17 #include <linux/ioport.h> 18 #include <linux/module.h> 19 #include <linux/of.h> 20 #include <linux/serdev.h> 21 #include <linux/serial_reg.h> 22 #include <linux/slab.h> 23 #include <linux/dev_printk.h> 24 25 #include <sound/core.h> 26 #include <sound/rawmidi.h> 27 #include <sound/initval.h> 28 29 MODULE_DESCRIPTION("Generic serial MIDI driver"); 30 MODULE_LICENSE("GPL"); 31 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 36 37 #define SERIAL_TX_STATE_ACTIVE 1 38 #define SERIAL_TX_STATE_WAKEUP 2 39 40 #define INTERNAL_BUF_SIZE 256 41 42 struct snd_serial_generic { 43 struct serdev_device *serdev; 44 45 struct snd_card *card; 46 struct snd_rawmidi *rmidi; 47 struct snd_rawmidi_substream *midi_output; 48 struct snd_rawmidi_substream *midi_input; 49 50 unsigned int baudrate; 51 52 unsigned long filemode; /* open status of file */ 53 struct work_struct tx_work; 54 unsigned long tx_state; 55 56 char tx_buf[INTERNAL_BUF_SIZE]; 57 }; 58 59 static void snd_serial_generic_tx_wakeup(struct snd_serial_generic *drvdata) 60 { 61 if (test_and_set_bit(SERIAL_TX_STATE_ACTIVE, &drvdata->tx_state)) 62 set_bit(SERIAL_TX_STATE_WAKEUP, &drvdata->tx_state); 63 64 schedule_work(&drvdata->tx_work); 65 } 66 67 static void snd_serial_generic_tx_work(struct work_struct *work) 68 { 69 int num_bytes; 70 struct snd_serial_generic *drvdata = container_of(work, struct snd_serial_generic, 71 tx_work); 72 struct snd_rawmidi_substream *substream = drvdata->midi_output; 73 74 clear_bit(SERIAL_TX_STATE_WAKEUP, &drvdata->tx_state); 75 76 while (!snd_rawmidi_transmit_empty(substream)) { 77 78 if (!test_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode)) 79 break; 80 81 num_bytes = snd_rawmidi_transmit_peek(substream, drvdata->tx_buf, 82 INTERNAL_BUF_SIZE); 83 num_bytes = serdev_device_write_buf(drvdata->serdev, drvdata->tx_buf, 84 num_bytes); 85 86 if (!num_bytes) 87 break; 88 89 snd_rawmidi_transmit_ack(substream, num_bytes); 90 91 if (!test_bit(SERIAL_TX_STATE_WAKEUP, &drvdata->tx_state)) 92 break; 93 } 94 95 clear_bit(SERIAL_TX_STATE_ACTIVE, &drvdata->tx_state); 96 } 97 98 static void snd_serial_generic_write_wakeup(struct serdev_device *serdev) 99 { 100 struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev); 101 102 snd_serial_generic_tx_wakeup(drvdata); 103 } 104 105 static size_t snd_serial_generic_receive_buf(struct serdev_device *serdev, 106 const u8 *buf, size_t count) 107 { 108 int ret; 109 struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev); 110 111 if (!test_bit(SERIAL_MODE_INPUT_OPEN, &drvdata->filemode)) 112 return 0; 113 114 ret = snd_rawmidi_receive(drvdata->midi_input, buf, count); 115 return ret < 0 ? 0 : ret; 116 } 117 118 static const struct serdev_device_ops snd_serial_generic_serdev_device_ops = { 119 .receive_buf = snd_serial_generic_receive_buf, 120 .write_wakeup = snd_serial_generic_write_wakeup 121 }; 122 123 static int snd_serial_generic_ensure_serdev_open(struct snd_serial_generic *drvdata) 124 { 125 int err; 126 unsigned int actual_baud; 127 128 if (drvdata->filemode) 129 return 0; 130 131 dev_dbg(drvdata->card->dev, "Opening serial port for card %s\n", 132 drvdata->card->shortname); 133 err = serdev_device_open(drvdata->serdev); 134 if (err < 0) 135 return err; 136 137 actual_baud = serdev_device_set_baudrate(drvdata->serdev, 138 drvdata->baudrate); 139 if (actual_baud != drvdata->baudrate) { 140 dev_warn(drvdata->card->dev, "requested %d baud for card %s but it was actually set to %d\n", 141 drvdata->baudrate, drvdata->card->shortname, actual_baud); 142 } 143 144 return 0; 145 } 146 147 static int snd_serial_generic_input_open(struct snd_rawmidi_substream *substream) 148 { 149 int err; 150 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data; 151 152 dev_dbg(drvdata->card->dev, "Opening input for card %s\n", 153 drvdata->card->shortname); 154 155 err = snd_serial_generic_ensure_serdev_open(drvdata); 156 if (err < 0) 157 return err; 158 159 set_bit(SERIAL_MODE_INPUT_OPEN, &drvdata->filemode); 160 drvdata->midi_input = substream; 161 return 0; 162 } 163 164 static int snd_serial_generic_input_close(struct snd_rawmidi_substream *substream) 165 { 166 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data; 167 168 dev_dbg(drvdata->card->dev, "Closing input for card %s\n", 169 drvdata->card->shortname); 170 171 clear_bit(SERIAL_MODE_INPUT_OPEN, &drvdata->filemode); 172 clear_bit(SERIAL_MODE_INPUT_TRIGGERED, &drvdata->filemode); 173 174 drvdata->midi_input = NULL; 175 176 if (!drvdata->filemode) 177 serdev_device_close(drvdata->serdev); 178 return 0; 179 } 180 181 static void snd_serial_generic_input_trigger(struct snd_rawmidi_substream *substream, 182 int up) 183 { 184 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data; 185 186 if (up) 187 set_bit(SERIAL_MODE_INPUT_TRIGGERED, &drvdata->filemode); 188 else 189 clear_bit(SERIAL_MODE_INPUT_TRIGGERED, &drvdata->filemode); 190 } 191 192 static int snd_serial_generic_output_open(struct snd_rawmidi_substream *substream) 193 { 194 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data; 195 int err; 196 197 dev_dbg(drvdata->card->dev, "Opening output for card %s\n", 198 drvdata->card->shortname); 199 200 err = snd_serial_generic_ensure_serdev_open(drvdata); 201 if (err < 0) 202 return err; 203 204 set_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode); 205 206 drvdata->midi_output = substream; 207 return 0; 208 }; 209 210 static int snd_serial_generic_output_close(struct snd_rawmidi_substream *substream) 211 { 212 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data; 213 214 dev_dbg(drvdata->card->dev, "Closing output for card %s\n", 215 drvdata->card->shortname); 216 217 clear_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode); 218 clear_bit(SERIAL_MODE_OUTPUT_TRIGGERED, &drvdata->filemode); 219 220 if (!drvdata->filemode) 221 serdev_device_close(drvdata->serdev); 222 223 drvdata->midi_output = NULL; 224 225 return 0; 226 }; 227 228 static void snd_serial_generic_output_trigger(struct snd_rawmidi_substream *substream, 229 int up) 230 { 231 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data; 232 233 if (up) 234 set_bit(SERIAL_MODE_OUTPUT_TRIGGERED, &drvdata->filemode); 235 else 236 clear_bit(SERIAL_MODE_OUTPUT_TRIGGERED, &drvdata->filemode); 237 238 if (up) 239 snd_serial_generic_tx_wakeup(drvdata); 240 } 241 242 static void snd_serial_generic_output_drain(struct snd_rawmidi_substream *substream) 243 { 244 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data; 245 246 /* Flush any pending characters */ 247 serdev_device_write_flush(drvdata->serdev); 248 cancel_work_sync(&drvdata->tx_work); 249 } 250 251 static const struct snd_rawmidi_ops snd_serial_generic_output = { 252 .open = snd_serial_generic_output_open, 253 .close = snd_serial_generic_output_close, 254 .trigger = snd_serial_generic_output_trigger, 255 .drain = snd_serial_generic_output_drain, 256 }; 257 258 static const struct snd_rawmidi_ops snd_serial_generic_input = { 259 .open = snd_serial_generic_input_open, 260 .close = snd_serial_generic_input_close, 261 .trigger = snd_serial_generic_input_trigger, 262 }; 263 264 static void snd_serial_generic_parse_dt(struct serdev_device *serdev, 265 struct snd_serial_generic *drvdata) 266 { 267 int err; 268 269 err = of_property_read_u32(serdev->dev.of_node, "current-speed", 270 &drvdata->baudrate); 271 if (err < 0) { 272 dev_dbg(drvdata->card->dev, 273 "MIDI device reading of current-speed DT param failed with error %d, using default of 38400\n", 274 err); 275 drvdata->baudrate = 38400; 276 } 277 278 } 279 280 static void snd_serial_generic_substreams(struct snd_rawmidi_str *stream, int dev_num) 281 { 282 struct snd_rawmidi_substream *substream; 283 284 list_for_each_entry(substream, &stream->substreams, list) { 285 sprintf(substream->name, "Serial MIDI %d-%d", dev_num, substream->number); 286 } 287 } 288 289 static int snd_serial_generic_rmidi(struct snd_serial_generic *drvdata, 290 int outs, int ins, struct snd_rawmidi **rmidi) 291 { 292 struct snd_rawmidi *rrawmidi; 293 int err; 294 295 err = snd_rawmidi_new(drvdata->card, drvdata->card->driver, 0, 296 outs, ins, &rrawmidi); 297 298 if (err < 0) 299 return err; 300 301 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, 302 &snd_serial_generic_input); 303 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 304 &snd_serial_generic_output); 305 strscpy(rrawmidi->name, drvdata->card->shortname); 306 307 snd_serial_generic_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT], 308 drvdata->serdev->ctrl->nr); 309 snd_serial_generic_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], 310 drvdata->serdev->ctrl->nr); 311 312 rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | 313 SNDRV_RAWMIDI_INFO_INPUT | 314 SNDRV_RAWMIDI_INFO_DUPLEX; 315 316 if (rmidi) 317 *rmidi = rrawmidi; 318 return 0; 319 } 320 321 static int snd_serial_generic_probe(struct serdev_device *serdev) 322 { 323 struct snd_card *card; 324 struct snd_serial_generic *drvdata; 325 int err; 326 327 err = snd_devm_card_new(&serdev->dev, SNDRV_DEFAULT_IDX1, 328 SNDRV_DEFAULT_STR1, THIS_MODULE, 329 sizeof(struct snd_serial_generic), &card); 330 331 if (err < 0) 332 return err; 333 334 strscpy(card->driver, "SerialMIDI"); 335 sprintf(card->shortname, "SerialMIDI-%d", serdev->ctrl->nr); 336 sprintf(card->longname, "Serial MIDI device at serial%d", serdev->ctrl->nr); 337 338 drvdata = card->private_data; 339 340 drvdata->serdev = serdev; 341 drvdata->card = card; 342 343 snd_serial_generic_parse_dt(serdev, drvdata); 344 345 INIT_WORK(&drvdata->tx_work, snd_serial_generic_tx_work); 346 347 err = snd_serial_generic_rmidi(drvdata, 1, 1, &drvdata->rmidi); 348 if (err < 0) 349 return err; 350 351 serdev_device_set_client_ops(serdev, &snd_serial_generic_serdev_device_ops); 352 serdev_device_set_drvdata(drvdata->serdev, drvdata); 353 354 err = snd_card_register(card); 355 if (err < 0) 356 return err; 357 358 return 0; 359 } 360 361 static const struct of_device_id snd_serial_generic_dt_ids[] = { 362 { .compatible = "serial-midi" }, 363 {}, 364 }; 365 366 MODULE_DEVICE_TABLE(of, snd_serial_generic_dt_ids); 367 368 static struct serdev_device_driver snd_serial_generic_driver = { 369 .driver = { 370 .name = "snd-serial-generic", 371 .of_match_table = snd_serial_generic_dt_ids, 372 }, 373 .probe = snd_serial_generic_probe, 374 }; 375 376 module_serdev_device_driver(snd_serial_generic_driver); 377