0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/err.h>
0014 #include <linux/init.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/io.h>
0017 #include <linux/ioport.h>
0018 #include <linux/module.h>
0019 #include <linux/of_device.h>
0020 #include <linux/serdev.h>
0021 #include <linux/serial_reg.h>
0022 #include <linux/slab.h>
0023 #include <linux/dev_printk.h>
0024
0025 #include <sound/core.h>
0026 #include <sound/rawmidi.h>
0027 #include <sound/initval.h>
0028
0029 MODULE_DESCRIPTION("Generic serial MIDI driver");
0030 MODULE_LICENSE("GPL");
0031
0032 #define SERIAL_MODE_INPUT_OPEN 1
0033 #define SERIAL_MODE_OUTPUT_OPEN 2
0034 #define SERIAL_MODE_INPUT_TRIGGERED 3
0035 #define SERIAL_MODE_OUTPUT_TRIGGERED 4
0036
0037 #define SERIAL_TX_STATE_ACTIVE 1
0038 #define SERIAL_TX_STATE_WAKEUP 2
0039
0040 struct snd_serial_generic {
0041 struct serdev_device *serdev;
0042
0043 struct snd_card *card;
0044 struct snd_rawmidi *rmidi;
0045 struct snd_rawmidi_substream *midi_output;
0046 struct snd_rawmidi_substream *midi_input;
0047
0048 unsigned int baudrate;
0049
0050 unsigned long filemode;
0051 struct work_struct tx_work;
0052 unsigned long tx_state;
0053
0054 };
0055
0056 static void snd_serial_generic_tx_wakeup(struct snd_serial_generic *drvdata)
0057 {
0058 if (test_and_set_bit(SERIAL_TX_STATE_ACTIVE, &drvdata->tx_state))
0059 set_bit(SERIAL_TX_STATE_WAKEUP, &drvdata->tx_state);
0060
0061 schedule_work(&drvdata->tx_work);
0062 }
0063
0064 #define INTERNAL_BUF_SIZE 256
0065
0066 static void snd_serial_generic_tx_work(struct work_struct *work)
0067 {
0068 static char buf[INTERNAL_BUF_SIZE];
0069 int num_bytes;
0070 struct snd_serial_generic *drvdata = container_of(work, struct snd_serial_generic,
0071 tx_work);
0072 struct snd_rawmidi_substream *substream = drvdata->midi_output;
0073
0074 clear_bit(SERIAL_TX_STATE_WAKEUP, &drvdata->tx_state);
0075
0076 while (!snd_rawmidi_transmit_empty(substream)) {
0077
0078 if (!test_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode))
0079 break;
0080
0081 num_bytes = snd_rawmidi_transmit_peek(substream, buf, INTERNAL_BUF_SIZE);
0082 num_bytes = serdev_device_write_buf(drvdata->serdev, buf, num_bytes);
0083
0084 if (!num_bytes)
0085 break;
0086
0087 snd_rawmidi_transmit_ack(substream, num_bytes);
0088
0089 if (!test_bit(SERIAL_TX_STATE_WAKEUP, &drvdata->tx_state))
0090 break;
0091 }
0092
0093 clear_bit(SERIAL_TX_STATE_ACTIVE, &drvdata->tx_state);
0094 }
0095
0096 static void snd_serial_generic_write_wakeup(struct serdev_device *serdev)
0097 {
0098 struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev);
0099
0100 snd_serial_generic_tx_wakeup(drvdata);
0101 }
0102
0103 static int snd_serial_generic_receive_buf(struct serdev_device *serdev,
0104 const unsigned char *buf, size_t count)
0105 {
0106 int ret;
0107 struct snd_serial_generic *drvdata = serdev_device_get_drvdata(serdev);
0108
0109 if (!test_bit(SERIAL_MODE_INPUT_OPEN, &drvdata->filemode))
0110 return 0;
0111
0112 ret = snd_rawmidi_receive(drvdata->midi_input, buf, count);
0113 return ret < 0 ? 0 : ret;
0114 }
0115
0116 static const struct serdev_device_ops snd_serial_generic_serdev_device_ops = {
0117 .receive_buf = snd_serial_generic_receive_buf,
0118 .write_wakeup = snd_serial_generic_write_wakeup
0119 };
0120
0121 static int snd_serial_generic_ensure_serdev_open(struct snd_serial_generic *drvdata)
0122 {
0123 int err;
0124 unsigned int actual_baud;
0125
0126 if (drvdata->filemode)
0127 return 0;
0128
0129 dev_dbg(drvdata->card->dev, "Opening serial port for card %s\n",
0130 drvdata->card->shortname);
0131 err = serdev_device_open(drvdata->serdev);
0132 if (err < 0)
0133 return err;
0134
0135 actual_baud = serdev_device_set_baudrate(drvdata->serdev,
0136 drvdata->baudrate);
0137 if (actual_baud != drvdata->baudrate) {
0138 dev_warn(drvdata->card->dev, "requested %d baud for card %s but it was actually set to %d\n",
0139 drvdata->baudrate, drvdata->card->shortname, actual_baud);
0140 }
0141
0142 return 0;
0143 }
0144
0145 static int snd_serial_generic_input_open(struct snd_rawmidi_substream *substream)
0146 {
0147 int err;
0148 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
0149
0150 dev_dbg(drvdata->card->dev, "Opening input for card %s\n",
0151 drvdata->card->shortname);
0152
0153 err = snd_serial_generic_ensure_serdev_open(drvdata);
0154 if (err < 0)
0155 return err;
0156
0157 set_bit(SERIAL_MODE_INPUT_OPEN, &drvdata->filemode);
0158 drvdata->midi_input = substream;
0159 return 0;
0160 }
0161
0162 static int snd_serial_generic_input_close(struct snd_rawmidi_substream *substream)
0163 {
0164 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
0165
0166 dev_dbg(drvdata->card->dev, "Closing input for card %s\n",
0167 drvdata->card->shortname);
0168
0169 clear_bit(SERIAL_MODE_INPUT_OPEN, &drvdata->filemode);
0170 clear_bit(SERIAL_MODE_INPUT_TRIGGERED, &drvdata->filemode);
0171
0172 drvdata->midi_input = NULL;
0173
0174 if (!drvdata->filemode)
0175 serdev_device_close(drvdata->serdev);
0176 return 0;
0177 }
0178
0179 static void snd_serial_generic_input_trigger(struct snd_rawmidi_substream *substream,
0180 int up)
0181 {
0182 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
0183
0184 if (up)
0185 set_bit(SERIAL_MODE_INPUT_TRIGGERED, &drvdata->filemode);
0186 else
0187 clear_bit(SERIAL_MODE_INPUT_TRIGGERED, &drvdata->filemode);
0188 }
0189
0190 static int snd_serial_generic_output_open(struct snd_rawmidi_substream *substream)
0191 {
0192 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
0193 int err;
0194
0195 dev_dbg(drvdata->card->dev, "Opening output for card %s\n",
0196 drvdata->card->shortname);
0197
0198 err = snd_serial_generic_ensure_serdev_open(drvdata);
0199 if (err < 0)
0200 return err;
0201
0202 set_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode);
0203
0204 drvdata->midi_output = substream;
0205 return 0;
0206 };
0207
0208 static int snd_serial_generic_output_close(struct snd_rawmidi_substream *substream)
0209 {
0210 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
0211
0212 dev_dbg(drvdata->card->dev, "Closing output for card %s\n",
0213 drvdata->card->shortname);
0214
0215 clear_bit(SERIAL_MODE_OUTPUT_OPEN, &drvdata->filemode);
0216 clear_bit(SERIAL_MODE_OUTPUT_TRIGGERED, &drvdata->filemode);
0217
0218 if (!drvdata->filemode)
0219 serdev_device_close(drvdata->serdev);
0220
0221 drvdata->midi_output = NULL;
0222
0223 return 0;
0224 };
0225
0226 static void snd_serial_generic_output_trigger(struct snd_rawmidi_substream *substream,
0227 int up)
0228 {
0229 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
0230
0231 if (up)
0232 set_bit(SERIAL_MODE_OUTPUT_TRIGGERED, &drvdata->filemode);
0233 else
0234 clear_bit(SERIAL_MODE_OUTPUT_TRIGGERED, &drvdata->filemode);
0235
0236 if (up)
0237 snd_serial_generic_tx_wakeup(drvdata);
0238 }
0239
0240 static void snd_serial_generic_output_drain(struct snd_rawmidi_substream *substream)
0241 {
0242 struct snd_serial_generic *drvdata = substream->rmidi->card->private_data;
0243
0244
0245 serdev_device_write_flush(drvdata->serdev);
0246 cancel_work_sync(&drvdata->tx_work);
0247 }
0248
0249 static const struct snd_rawmidi_ops snd_serial_generic_output = {
0250 .open = snd_serial_generic_output_open,
0251 .close = snd_serial_generic_output_close,
0252 .trigger = snd_serial_generic_output_trigger,
0253 .drain = snd_serial_generic_output_drain,
0254 };
0255
0256 static const struct snd_rawmidi_ops snd_serial_generic_input = {
0257 .open = snd_serial_generic_input_open,
0258 .close = snd_serial_generic_input_close,
0259 .trigger = snd_serial_generic_input_trigger,
0260 };
0261
0262 static void snd_serial_generic_parse_dt(struct serdev_device *serdev,
0263 struct snd_serial_generic *drvdata)
0264 {
0265 int err;
0266
0267 err = of_property_read_u32(serdev->dev.of_node, "current-speed",
0268 &drvdata->baudrate);
0269 if (err < 0) {
0270 dev_dbg(drvdata->card->dev,
0271 "MIDI device reading of current-speed DT param failed with error %d, using default of 38400\n",
0272 err);
0273 drvdata->baudrate = 38400;
0274 }
0275
0276 }
0277
0278 static void snd_serial_generic_substreams(struct snd_rawmidi_str *stream, int dev_num)
0279 {
0280 struct snd_rawmidi_substream *substream;
0281
0282 list_for_each_entry(substream, &stream->substreams, list) {
0283 sprintf(substream->name, "Serial MIDI %d-%d", dev_num, substream->number);
0284 }
0285 }
0286
0287 static int snd_serial_generic_rmidi(struct snd_serial_generic *drvdata,
0288 int outs, int ins, struct snd_rawmidi **rmidi)
0289 {
0290 struct snd_rawmidi *rrawmidi;
0291 int err;
0292
0293 err = snd_rawmidi_new(drvdata->card, drvdata->card->driver, 0,
0294 outs, ins, &rrawmidi);
0295
0296 if (err < 0)
0297 return err;
0298
0299 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT,
0300 &snd_serial_generic_input);
0301 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
0302 &snd_serial_generic_output);
0303 strcpy(rrawmidi->name, drvdata->card->shortname);
0304
0305 snd_serial_generic_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT],
0306 drvdata->serdev->ctrl->nr);
0307 snd_serial_generic_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],
0308 drvdata->serdev->ctrl->nr);
0309
0310 rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
0311 SNDRV_RAWMIDI_INFO_INPUT |
0312 SNDRV_RAWMIDI_INFO_DUPLEX;
0313
0314 if (rmidi)
0315 *rmidi = rrawmidi;
0316 return 0;
0317 }
0318
0319 static int snd_serial_generic_probe(struct serdev_device *serdev)
0320 {
0321 struct snd_card *card;
0322 struct snd_serial_generic *drvdata;
0323 int err;
0324
0325 err = snd_devm_card_new(&serdev->dev, SNDRV_DEFAULT_IDX1,
0326 SNDRV_DEFAULT_STR1, THIS_MODULE,
0327 sizeof(struct snd_serial_generic), &card);
0328
0329 if (err < 0)
0330 return err;
0331
0332 strcpy(card->driver, "SerialMIDI");
0333 sprintf(card->shortname, "SerialMIDI-%d", serdev->ctrl->nr);
0334 sprintf(card->longname, "Serial MIDI device at serial%d", serdev->ctrl->nr);
0335
0336 drvdata = card->private_data;
0337
0338 drvdata->serdev = serdev;
0339 drvdata->card = card;
0340
0341 snd_serial_generic_parse_dt(serdev, drvdata);
0342
0343 INIT_WORK(&drvdata->tx_work, snd_serial_generic_tx_work);
0344
0345 err = snd_serial_generic_rmidi(drvdata, 1, 1, &drvdata->rmidi);
0346 if (err < 0)
0347 return err;
0348
0349 serdev_device_set_client_ops(serdev, &snd_serial_generic_serdev_device_ops);
0350 serdev_device_set_drvdata(drvdata->serdev, drvdata);
0351
0352 err = snd_card_register(card);
0353 if (err < 0)
0354 return err;
0355
0356 return 0;
0357 }
0358
0359 static const struct of_device_id snd_serial_generic_dt_ids[] = {
0360 { .compatible = "serial-midi" },
0361 {},
0362 };
0363
0364 MODULE_DEVICE_TABLE(of, snd_serial_generic_dt_ids);
0365
0366 static struct serdev_device_driver snd_serial_generic_driver = {
0367 .driver = {
0368 .name = "snd-serial-generic",
0369 .of_match_table = of_match_ptr(snd_serial_generic_dt_ids),
0370 },
0371 .probe = snd_serial_generic_probe,
0372 };
0373
0374 module_serdev_device_driver(snd_serial_generic_driver);