1062 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* 3 * ALSA Driver for Ego Systems Inc. (ESI) Miditerminal 41404 * Copyright (c) 2006 by Matthias König <mk@phasorlab.de>5 */6 7#include <linux/init.h>8#include <linux/platform_device.h>9#include <linux/parport.h>10#include <linux/spinlock.h>11#include <linux/module.h>12#include <linux/delay.h>13#include <linux/slab.h>14#include <sound/core.h>15#include <sound/initval.h>16#include <sound/rawmidi.h>17#include <sound/control.h>18 19#define CARD_NAME "Miditerminal 4140"20#define DRIVER_NAME "MTS64"21#define PLATFORM_DRIVER "snd_mts64"22 23static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;24static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;25static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;26 27static struct platform_device *platform_devices[SNDRV_CARDS]; 28static int device_count;29 30module_param_array(index, int, NULL, 0444);31MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");32module_param_array(id, charp, NULL, 0444);33MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");34module_param_array(enable, bool, NULL, 0444);35MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");36 37MODULE_AUTHOR("Matthias Koenig <mk@phasorlab.de>");38MODULE_DESCRIPTION("ESI Miditerminal 4140");39MODULE_LICENSE("GPL");40 41/*********************************************************************42 * Chip specific43 *********************************************************************/44#define MTS64_NUM_INPUT_PORTS 545#define MTS64_NUM_OUTPUT_PORTS 446#define MTS64_SMPTE_SUBSTREAM 447 48struct mts64 {49 spinlock_t lock;50 struct snd_card *card;51 struct snd_rawmidi *rmidi;52 struct pardevice *pardev;53 int open_count;54 int current_midi_output_port;55 int current_midi_input_port;56 u8 mode[MTS64_NUM_INPUT_PORTS];57 struct snd_rawmidi_substream *midi_input_substream[MTS64_NUM_INPUT_PORTS];58 int smpte_switch;59 u8 time[4]; /* [0]=hh, [1]=mm, [2]=ss, [3]=ff */60 u8 fps;61};62 63static int snd_mts64_free(struct mts64 *mts)64{65 kfree(mts);66 return 0;67}68 69static int snd_mts64_create(struct snd_card *card,70 struct pardevice *pardev,71 struct mts64 **rchip)72{73 struct mts64 *mts;74 75 *rchip = NULL;76 77 mts = kzalloc(sizeof(struct mts64), GFP_KERNEL);78 if (mts == NULL) 79 return -ENOMEM;80 81 /* Init chip specific data */82 spin_lock_init(&mts->lock);83 mts->card = card;84 mts->pardev = pardev;85 mts->current_midi_output_port = -1;86 mts->current_midi_input_port = -1;87 88 *rchip = mts;89 90 return 0;91}92 93/*********************************************************************94 * HW register related constants95 *********************************************************************/96 97/* Status Bits */98#define MTS64_STAT_BSY 0x8099#define MTS64_STAT_BIT_SET 0x20 /* readout process, bit is set */100#define MTS64_STAT_PORT 0x10 /* read byte is a port number */101 102/* Control Bits */103#define MTS64_CTL_READOUT 0x08 /* enable readout */104#define MTS64_CTL_WRITE_CMD 0x06 105#define MTS64_CTL_WRITE_DATA 0x02 106#define MTS64_CTL_STROBE 0x01 107 108/* Command */109#define MTS64_CMD_RESET 0xfe110#define MTS64_CMD_PROBE 0x8f /* Used in probing procedure */111#define MTS64_CMD_SMPTE_SET_TIME 0xe8112#define MTS64_CMD_SMPTE_SET_FPS 0xee113#define MTS64_CMD_SMPTE_STOP 0xef114#define MTS64_CMD_SMPTE_FPS_24 0xe3115#define MTS64_CMD_SMPTE_FPS_25 0xe2116#define MTS64_CMD_SMPTE_FPS_2997 0xe4 117#define MTS64_CMD_SMPTE_FPS_30D 0xe1118#define MTS64_CMD_SMPTE_FPS_30 0xe0119#define MTS64_CMD_COM_OPEN 0xf8 /* setting the communication mode */120#define MTS64_CMD_COM_CLOSE1 0xff /* clearing communication mode */121#define MTS64_CMD_COM_CLOSE2 0xf5122 123/*********************************************************************124 * Hardware specific functions125 *********************************************************************/126static void mts64_enable_readout(struct parport *p);127static void mts64_disable_readout(struct parport *p);128static int mts64_device_ready(struct parport *p);129static int mts64_device_init(struct parport *p);130static int mts64_device_open(struct mts64 *mts);131static int mts64_device_close(struct mts64 *mts);132static u8 mts64_map_midi_input(u8 c);133static int mts64_probe(struct parport *p);134static u16 mts64_read(struct parport *p);135static u8 mts64_read_char(struct parport *p);136static void mts64_smpte_start(struct parport *p,137 u8 hours, u8 minutes,138 u8 seconds, u8 frames,139 u8 idx);140static void mts64_smpte_stop(struct parport *p);141static void mts64_write_command(struct parport *p, u8 c);142static void mts64_write_data(struct parport *p, u8 c);143static void mts64_write_midi(struct mts64 *mts, u8 c, int midiport);144 145 146/* Enables the readout procedure147 *148 * Before we can read a midi byte from the device, we have to set149 * bit 3 of control port.150 */151static void mts64_enable_readout(struct parport *p)152{153 u8 c;154 155 c = parport_read_control(p);156 c |= MTS64_CTL_READOUT;157 parport_write_control(p, c); 158}159 160/* Disables readout 161 *162 * Readout is disabled by clearing bit 3 of control163 */164static void mts64_disable_readout(struct parport *p)165{166 u8 c;167 168 c = parport_read_control(p);169 c &= ~MTS64_CTL_READOUT;170 parport_write_control(p, c);171}172 173/* waits for device ready174 *175 * Checks if BUSY (Bit 7 of status) is clear176 * 1 device ready177 * 0 failure178 */179static int mts64_device_ready(struct parport *p)180{181 int i;182 u8 c;183 184 for (i = 0; i < 0xffff; ++i) {185 c = parport_read_status(p);186 c &= MTS64_STAT_BSY;187 if (c != 0) 188 return 1;189 } 190 191 return 0;192}193 194/* Init device (LED blinking startup magic)195 *196 * Returns:197 * 0 init ok198 * -EIO failure199 */200static int mts64_device_init(struct parport *p)201{202 int i;203 204 mts64_write_command(p, MTS64_CMD_RESET);205 206 for (i = 0; i < 64; ++i) {207 msleep(100);208 209 if (mts64_probe(p) == 0) {210 /* success */211 mts64_disable_readout(p);212 return 0;213 }214 }215 mts64_disable_readout(p);216 217 return -EIO;218}219 220/* 221 * Opens the device (set communication mode)222 */223static int mts64_device_open(struct mts64 *mts)224{225 int i;226 struct parport *p = mts->pardev->port;227 228 for (i = 0; i < 5; ++i)229 mts64_write_command(p, MTS64_CMD_COM_OPEN);230 231 return 0;232}233 234/* 235 * Close device (clear communication mode)236 */237static int mts64_device_close(struct mts64 *mts)238{239 int i;240 struct parport *p = mts->pardev->port;241 242 for (i = 0; i < 5; ++i) {243 mts64_write_command(p, MTS64_CMD_COM_CLOSE1);244 mts64_write_command(p, MTS64_CMD_COM_CLOSE2);245 }246 247 return 0;248}249 250/* map hardware port to substream number251 * 252 * When reading a byte from the device, the device tells us253 * on what port the byte is. This HW port has to be mapped to254 * the midiport (substream number).255 * substream 0-3 are Midiports 1-4256 * substream 4 is SMPTE Timecode257 * The mapping is done by the table:258 * HW | 0 | 1 | 2 | 3 | 4 259 * SW | 0 | 1 | 4 | 2 | 3260 */261static u8 mts64_map_midi_input(u8 c)262{263 static const u8 map[] = { 0, 1, 4, 2, 3 };264 265 return map[c];266}267 268 269/* Probe parport for device270 *271 * Do we have a Miditerminal 4140 on parport? 272 * Returns:273 * 0 device found274 * -ENODEV no device275 */276static int mts64_probe(struct parport *p)277{278 u8 c;279 280 mts64_smpte_stop(p);281 mts64_write_command(p, MTS64_CMD_PROBE);282 283 msleep(50);284 285 c = mts64_read(p);286 287 c &= 0x00ff;288 if (c != MTS64_CMD_PROBE) 289 return -ENODEV;290 else 291 return 0;292 293}294 295/* Read byte incl. status from device296 *297 * Returns:298 * data in lower 8 bits and status in upper 8 bits299 */300static u16 mts64_read(struct parport *p)301{302 u8 data, status;303 304 mts64_device_ready(p);305 mts64_enable_readout(p);306 status = parport_read_status(p);307 data = mts64_read_char(p);308 mts64_disable_readout(p);309 310 return (status << 8) | data;311}312 313/* Read a byte from device314 *315 * Note, that readout mode has to be enabled.316 * readout procedure is as follows: 317 * - Write number of the Bit to read to DATA318 * - Read STATUS319 * - Bit 5 of STATUS indicates if Bit is set320 *321 * Returns:322 * Byte read from device323 */324static u8 mts64_read_char(struct parport *p)325{326 u8 c = 0;327 u8 status;328 u8 i;329 330 for (i = 0; i < 8; ++i) {331 parport_write_data(p, i);332 c >>= 1;333 status = parport_read_status(p);334 if (status & MTS64_STAT_BIT_SET) 335 c |= 0x80;336 }337 338 return c;339}340 341/* Starts SMPTE Timecode generation342 *343 * The device creates SMPTE Timecode by hardware.344 * 0 24 fps345 * 1 25 fps346 * 2 29.97 fps347 * 3 30 fps (Drop-frame)348 * 4 30 fps349 */350static void mts64_smpte_start(struct parport *p,351 u8 hours, u8 minutes,352 u8 seconds, u8 frames,353 u8 idx)354{355 static const u8 fps[5] = { MTS64_CMD_SMPTE_FPS_24,356 MTS64_CMD_SMPTE_FPS_25,357 MTS64_CMD_SMPTE_FPS_2997, 358 MTS64_CMD_SMPTE_FPS_30D,359 MTS64_CMD_SMPTE_FPS_30 };360 361 mts64_write_command(p, MTS64_CMD_SMPTE_SET_TIME);362 mts64_write_command(p, frames);363 mts64_write_command(p, seconds);364 mts64_write_command(p, minutes);365 mts64_write_command(p, hours);366 367 mts64_write_command(p, MTS64_CMD_SMPTE_SET_FPS);368 mts64_write_command(p, fps[idx]);369}370 371/* Stops SMPTE Timecode generation372 */373static void mts64_smpte_stop(struct parport *p)374{375 mts64_write_command(p, MTS64_CMD_SMPTE_STOP);376}377 378/* Write a command byte to device379 */380static void mts64_write_command(struct parport *p, u8 c)381{382 mts64_device_ready(p);383 384 parport_write_data(p, c);385 386 parport_write_control(p, MTS64_CTL_WRITE_CMD);387 parport_write_control(p, MTS64_CTL_WRITE_CMD | MTS64_CTL_STROBE);388 parport_write_control(p, MTS64_CTL_WRITE_CMD);389}390 391/* Write a data byte to device 392 */393static void mts64_write_data(struct parport *p, u8 c)394{395 mts64_device_ready(p);396 397 parport_write_data(p, c);398 399 parport_write_control(p, MTS64_CTL_WRITE_DATA);400 parport_write_control(p, MTS64_CTL_WRITE_DATA | MTS64_CTL_STROBE);401 parport_write_control(p, MTS64_CTL_WRITE_DATA);402}403 404/* Write a MIDI byte to midiport405 *406 * midiport ranges from 0-3 and maps to Ports 1-4407 * assumptions: communication mode is on408 */409static void mts64_write_midi(struct mts64 *mts, u8 c,410 int midiport)411{412 struct parport *p = mts->pardev->port;413 414 /* check current midiport */415 if (mts->current_midi_output_port != midiport)416 mts64_write_command(p, midiport);417 418 /* write midi byte */419 mts64_write_data(p, c);420}421 422/*********************************************************************423 * Control elements424 *********************************************************************/425 426/* SMPTE Switch */427#define snd_mts64_ctl_smpte_switch_info snd_ctl_boolean_mono_info428 429static int snd_mts64_ctl_smpte_switch_get(struct snd_kcontrol* kctl,430 struct snd_ctl_elem_value *uctl)431{432 struct mts64 *mts = snd_kcontrol_chip(kctl);433 434 spin_lock_irq(&mts->lock);435 uctl->value.integer.value[0] = mts->smpte_switch;436 spin_unlock_irq(&mts->lock);437 438 return 0;439}440 441/* smpte_switch is not accessed from IRQ handler, so we just need442 to protect the HW access */443static int snd_mts64_ctl_smpte_switch_put(struct snd_kcontrol* kctl,444 struct snd_ctl_elem_value *uctl)445{446 struct mts64 *mts = snd_kcontrol_chip(kctl);447 int changed = 0;448 int val = !!uctl->value.integer.value[0];449 450 spin_lock_irq(&mts->lock);451 if (mts->smpte_switch == val)452 goto __out;453 454 changed = 1;455 mts->smpte_switch = val;456 if (mts->smpte_switch) {457 mts64_smpte_start(mts->pardev->port,458 mts->time[0], mts->time[1],459 mts->time[2], mts->time[3],460 mts->fps);461 } else {462 mts64_smpte_stop(mts->pardev->port);463 }464__out:465 spin_unlock_irq(&mts->lock);466 return changed;467}468 469static const struct snd_kcontrol_new mts64_ctl_smpte_switch = {470 .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,471 .name = "SMPTE Playback Switch",472 .index = 0,473 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,474 .private_value = 0,475 .info = snd_mts64_ctl_smpte_switch_info,476 .get = snd_mts64_ctl_smpte_switch_get,477 .put = snd_mts64_ctl_smpte_switch_put478};479 480/* Time */481static int snd_mts64_ctl_smpte_time_h_info(struct snd_kcontrol *kctl,482 struct snd_ctl_elem_info *uinfo)483{484 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;485 uinfo->count = 1;486 uinfo->value.integer.min = 0;487 uinfo->value.integer.max = 23;488 return 0;489}490 491static int snd_mts64_ctl_smpte_time_f_info(struct snd_kcontrol *kctl,492 struct snd_ctl_elem_info *uinfo)493{494 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;495 uinfo->count = 1;496 uinfo->value.integer.min = 0;497 uinfo->value.integer.max = 99;498 return 0;499}500 501static int snd_mts64_ctl_smpte_time_info(struct snd_kcontrol *kctl,502 struct snd_ctl_elem_info *uinfo)503{504 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;505 uinfo->count = 1;506 uinfo->value.integer.min = 0;507 uinfo->value.integer.max = 59;508 return 0;509}510 511static int snd_mts64_ctl_smpte_time_get(struct snd_kcontrol *kctl,512 struct snd_ctl_elem_value *uctl)513{514 struct mts64 *mts = snd_kcontrol_chip(kctl);515 int idx = kctl->private_value;516 517 spin_lock_irq(&mts->lock);518 uctl->value.integer.value[0] = mts->time[idx];519 spin_unlock_irq(&mts->lock);520 521 return 0;522}523 524static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl,525 struct snd_ctl_elem_value *uctl)526{527 struct mts64 *mts = snd_kcontrol_chip(kctl);528 int idx = kctl->private_value;529 unsigned int time = uctl->value.integer.value[0] % 60;530 int changed = 0;531 532 spin_lock_irq(&mts->lock);533 if (mts->time[idx] != time) {534 changed = 1;535 mts->time[idx] = time;536 }537 spin_unlock_irq(&mts->lock);538 539 return changed;540}541 542static const struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {543 .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,544 .name = "SMPTE Time Hours",545 .index = 0,546 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,547 .private_value = 0,548 .info = snd_mts64_ctl_smpte_time_h_info,549 .get = snd_mts64_ctl_smpte_time_get,550 .put = snd_mts64_ctl_smpte_time_put551};552 553static const struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {554 .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,555 .name = "SMPTE Time Minutes",556 .index = 0,557 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,558 .private_value = 1,559 .info = snd_mts64_ctl_smpte_time_info,560 .get = snd_mts64_ctl_smpte_time_get,561 .put = snd_mts64_ctl_smpte_time_put562};563 564static const struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {565 .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,566 .name = "SMPTE Time Seconds",567 .index = 0,568 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,569 .private_value = 2,570 .info = snd_mts64_ctl_smpte_time_info,571 .get = snd_mts64_ctl_smpte_time_get,572 .put = snd_mts64_ctl_smpte_time_put573};574 575static const struct snd_kcontrol_new mts64_ctl_smpte_time_frames = {576 .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,577 .name = "SMPTE Time Frames",578 .index = 0,579 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,580 .private_value = 3,581 .info = snd_mts64_ctl_smpte_time_f_info,582 .get = snd_mts64_ctl_smpte_time_get,583 .put = snd_mts64_ctl_smpte_time_put584};585 586/* FPS */587static int snd_mts64_ctl_smpte_fps_info(struct snd_kcontrol *kctl,588 struct snd_ctl_elem_info *uinfo)589{590 static const char * const texts[5] = {591 "24", "25", "29.97", "30D", "30"592 };593 594 return snd_ctl_enum_info(uinfo, 1, 5, texts);595}596 597static int snd_mts64_ctl_smpte_fps_get(struct snd_kcontrol *kctl,598 struct snd_ctl_elem_value *uctl)599{600 struct mts64 *mts = snd_kcontrol_chip(kctl);601 602 spin_lock_irq(&mts->lock);603 uctl->value.enumerated.item[0] = mts->fps;604 spin_unlock_irq(&mts->lock);605 606 return 0;607}608 609static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl,610 struct snd_ctl_elem_value *uctl)611{612 struct mts64 *mts = snd_kcontrol_chip(kctl);613 int changed = 0;614 615 if (uctl->value.enumerated.item[0] >= 5)616 return -EINVAL;617 spin_lock_irq(&mts->lock);618 if (mts->fps != uctl->value.enumerated.item[0]) {619 changed = 1;620 mts->fps = uctl->value.enumerated.item[0];621 }622 spin_unlock_irq(&mts->lock);623 624 return changed;625}626 627static const struct snd_kcontrol_new mts64_ctl_smpte_fps = {628 .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,629 .name = "SMPTE Fps",630 .index = 0,631 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,632 .private_value = 0,633 .info = snd_mts64_ctl_smpte_fps_info,634 .get = snd_mts64_ctl_smpte_fps_get,635 .put = snd_mts64_ctl_smpte_fps_put636};637 638 639static int snd_mts64_ctl_create(struct snd_card *card,640 struct mts64 *mts)641{642 int err, i;643 static const struct snd_kcontrol_new *control[] = {644 &mts64_ctl_smpte_switch,645 &mts64_ctl_smpte_time_hours,646 &mts64_ctl_smpte_time_minutes,647 &mts64_ctl_smpte_time_seconds,648 &mts64_ctl_smpte_time_frames,649 &mts64_ctl_smpte_fps,650 NULL };651 652 for (i = 0; control[i]; ++i) {653 err = snd_ctl_add(card, snd_ctl_new1(control[i], mts));654 if (err < 0) {655 dev_dbg(card->dev, "Cannot create control: %s\n",656 control[i]->name);657 return err;658 }659 }660 661 return 0;662}663 664/*********************************************************************665 * Rawmidi666 *********************************************************************/667#define MTS64_MODE_INPUT_TRIGGERED 0x01668 669static int snd_mts64_rawmidi_open(struct snd_rawmidi_substream *substream)670{671 struct mts64 *mts = substream->rmidi->private_data;672 673 if (mts->open_count == 0) {674 /* We don't need a spinlock here, because this is just called 675 if the device has not been opened before. 676 So there aren't any IRQs from the device */677 mts64_device_open(mts);678 679 msleep(50);680 }681 ++(mts->open_count);682 683 return 0;684}685 686static int snd_mts64_rawmidi_close(struct snd_rawmidi_substream *substream)687{688 struct mts64 *mts = substream->rmidi->private_data;689 unsigned long flags;690 691 --(mts->open_count);692 if (mts->open_count == 0) {693 /* We need the spinlock_irqsave here because we can still694 have IRQs at this point */695 spin_lock_irqsave(&mts->lock, flags);696 mts64_device_close(mts);697 spin_unlock_irqrestore(&mts->lock, flags);698 699 msleep(500);700 701 } else if (mts->open_count < 0)702 mts->open_count = 0;703 704 return 0;705}706 707static void snd_mts64_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,708 int up)709{710 struct mts64 *mts = substream->rmidi->private_data;711 u8 data;712 unsigned long flags;713 714 spin_lock_irqsave(&mts->lock, flags);715 while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {716 mts64_write_midi(mts, data, substream->number+1);717 snd_rawmidi_transmit_ack(substream, 1);718 }719 spin_unlock_irqrestore(&mts->lock, flags);720}721 722static void snd_mts64_rawmidi_input_trigger(struct snd_rawmidi_substream *substream,723 int up)724{725 struct mts64 *mts = substream->rmidi->private_data;726 unsigned long flags;727 728 spin_lock_irqsave(&mts->lock, flags);729 if (up)730 mts->mode[substream->number] |= MTS64_MODE_INPUT_TRIGGERED;731 else732 mts->mode[substream->number] &= ~MTS64_MODE_INPUT_TRIGGERED;733 734 spin_unlock_irqrestore(&mts->lock, flags);735}736 737static const struct snd_rawmidi_ops snd_mts64_rawmidi_output_ops = {738 .open = snd_mts64_rawmidi_open,739 .close = snd_mts64_rawmidi_close,740 .trigger = snd_mts64_rawmidi_output_trigger741};742 743static const struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = {744 .open = snd_mts64_rawmidi_open,745 .close = snd_mts64_rawmidi_close,746 .trigger = snd_mts64_rawmidi_input_trigger747};748 749/* Create and initialize the rawmidi component */750static int snd_mts64_rawmidi_create(struct snd_card *card)751{752 struct mts64 *mts = card->private_data;753 struct snd_rawmidi *rmidi;754 struct snd_rawmidi_substream *substream;755 struct list_head *list;756 int err;757 758 err = snd_rawmidi_new(card, CARD_NAME, 0, 759 MTS64_NUM_OUTPUT_PORTS, 760 MTS64_NUM_INPUT_PORTS, 761 &rmidi);762 if (err < 0) 763 return err;764 765 rmidi->private_data = mts;766 strcpy(rmidi->name, CARD_NAME);767 rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |768 SNDRV_RAWMIDI_INFO_INPUT |769 SNDRV_RAWMIDI_INFO_DUPLEX;770 771 mts->rmidi = rmidi;772 773 /* register rawmidi ops */774 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 775 &snd_mts64_rawmidi_output_ops);776 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 777 &snd_mts64_rawmidi_input_ops);778 779 /* name substreams */780 /* output */781 list_for_each(list, 782 &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {783 substream = list_entry(list, struct snd_rawmidi_substream, list);784 sprintf(substream->name,785 "Miditerminal %d", substream->number+1);786 }787 /* input */788 list_for_each(list, 789 &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {790 substream = list_entry(list, struct snd_rawmidi_substream, list);791 mts->midi_input_substream[substream->number] = substream;792 switch(substream->number) {793 case MTS64_SMPTE_SUBSTREAM:794 strcpy(substream->name, "Miditerminal SMPTE");795 break;796 default:797 sprintf(substream->name,798 "Miditerminal %d", substream->number+1);799 }800 }801 802 /* controls */803 err = snd_mts64_ctl_create(card, mts);804 805 return err;806}807 808/*********************************************************************809 * parport stuff810 *********************************************************************/811static void snd_mts64_interrupt(void *private)812{813 struct mts64 *mts = ((struct snd_card*)private)->private_data;814 u16 ret;815 u8 status, data;816 struct snd_rawmidi_substream *substream;817 818 if (!mts)819 return;820 821 spin_lock(&mts->lock);822 ret = mts64_read(mts->pardev->port);823 data = ret & 0x00ff;824 status = ret >> 8;825 826 if (status & MTS64_STAT_PORT) {827 mts->current_midi_input_port = mts64_map_midi_input(data);828 } else {829 if (mts->current_midi_input_port == -1) 830 goto __out;831 substream = mts->midi_input_substream[mts->current_midi_input_port];832 if (mts->mode[substream->number] & MTS64_MODE_INPUT_TRIGGERED)833 snd_rawmidi_receive(substream, &data, 1);834 }835__out:836 spin_unlock(&mts->lock);837}838 839static void snd_mts64_attach(struct parport *p)840{841 struct platform_device *device;842 843 device = platform_device_alloc(PLATFORM_DRIVER, device_count);844 if (!device)845 return;846 847 /* Temporary assignment to forward the parport */848 platform_set_drvdata(device, p);849 850 if (platform_device_add(device) < 0) {851 platform_device_put(device);852 return;853 }854 855 /* Since we dont get the return value of probe856 * We need to check if device probing succeeded or not */857 if (!platform_get_drvdata(device)) {858 platform_device_unregister(device);859 return;860 }861 862 /* register device in global table */863 platform_devices[device_count] = device;864 device_count++;865}866 867static void snd_mts64_detach(struct parport *p)868{869 /* nothing to do here */870}871 872static int snd_mts64_dev_probe(struct pardevice *pardev)873{874 if (strcmp(pardev->name, DRIVER_NAME))875 return -ENODEV;876 877 return 0;878}879 880static struct parport_driver mts64_parport_driver = {881 .name = "mts64",882 .probe = snd_mts64_dev_probe,883 .match_port = snd_mts64_attach,884 .detach = snd_mts64_detach,885};886 887/*********************************************************************888 * platform stuff889 *********************************************************************/890static void snd_mts64_card_private_free(struct snd_card *card)891{892 struct mts64 *mts = card->private_data;893 struct pardevice *pardev = mts->pardev;894 895 if (pardev) {896 parport_release(pardev);897 parport_unregister_device(pardev);898 }899 900 snd_mts64_free(mts);901}902 903static int snd_mts64_probe(struct platform_device *pdev)904{905 struct pardevice *pardev;906 struct parport *p;907 int dev = pdev->id;908 struct snd_card *card = NULL;909 struct mts64 *mts = NULL;910 int err;911 struct pardev_cb mts64_cb = {912 .preempt = NULL,913 .wakeup = NULL,914 .irq_func = snd_mts64_interrupt, /* ISR */915 .flags = PARPORT_DEV_EXCL, /* flags */916 };917 918 p = platform_get_drvdata(pdev);919 platform_set_drvdata(pdev, NULL);920 921 if (dev >= SNDRV_CARDS)922 return -ENODEV;923 if (!enable[dev]) 924 return -ENOENT;925 926 err = snd_card_new(&pdev->dev, index[dev], id[dev], THIS_MODULE,927 0, &card);928 if (err < 0) {929 dev_dbg(&pdev->dev, "Cannot create card\n");930 return err;931 }932 strcpy(card->driver, DRIVER_NAME);933 strcpy(card->shortname, "ESI " CARD_NAME);934 sprintf(card->longname, "%s at 0x%lx, irq %i", 935 card->shortname, p->base, p->irq);936 937 mts64_cb.private = card; /* private */938 pardev = parport_register_dev_model(p, /* port */939 DRIVER_NAME, /* name */940 &mts64_cb, /* callbacks */941 pdev->id); /* device number */942 if (!pardev) {943 dev_dbg(card->dev, "Cannot register pardevice\n");944 err = -EIO;945 goto __err;946 }947 948 /* claim parport */949 if (parport_claim(pardev)) {950 dev_dbg(card->dev, "Cannot claim parport 0x%lx\n", pardev->port->base);951 err = -EIO;952 goto free_pardev;953 }954 955 err = snd_mts64_create(card, pardev, &mts);956 if (err < 0) {957 dev_dbg(card->dev, "Cannot create main component\n");958 goto release_pardev;959 }960 card->private_data = mts;961 card->private_free = snd_mts64_card_private_free;962 963 err = mts64_probe(p);964 if (err) {965 err = -EIO;966 goto __err;967 }968 969 err = snd_mts64_rawmidi_create(card);970 if (err < 0) {971 dev_dbg(card->dev, "Creating Rawmidi component failed\n");972 goto __err;973 }974 975 /* init device */976 err = mts64_device_init(p);977 if (err < 0)978 goto __err;979 980 platform_set_drvdata(pdev, card);981 982 /* At this point card will be usable */983 err = snd_card_register(card);984 if (err < 0) {985 dev_dbg(card->dev, "Cannot register card\n");986 goto __err;987 }988 989 dev_info(card->dev, "ESI Miditerminal 4140 on 0x%lx\n", p->base);990 return 0;991 992release_pardev:993 parport_release(pardev);994free_pardev:995 parport_unregister_device(pardev);996__err:997 snd_card_free(card);998 return err;999}1000 1001static void snd_mts64_remove(struct platform_device *pdev)1002{1003 struct snd_card *card = platform_get_drvdata(pdev);1004 1005 if (card)1006 snd_card_free(card);1007}1008 1009static struct platform_driver snd_mts64_driver = {1010 .probe = snd_mts64_probe,1011 .remove_new = snd_mts64_remove,1012 .driver = {1013 .name = PLATFORM_DRIVER,1014 }1015};1016 1017/*********************************************************************1018 * module init stuff1019 *********************************************************************/1020static void snd_mts64_unregister_all(void)1021{1022 int i;1023 1024 for (i = 0; i < SNDRV_CARDS; ++i) {1025 if (platform_devices[i]) {1026 platform_device_unregister(platform_devices[i]);1027 platform_devices[i] = NULL;1028 }1029 } 1030 platform_driver_unregister(&snd_mts64_driver);1031 parport_unregister_driver(&mts64_parport_driver);1032}1033 1034static int __init snd_mts64_module_init(void)1035{1036 int err;1037 1038 err = platform_driver_register(&snd_mts64_driver);1039 if (err < 0)1040 return err;1041 1042 if (parport_register_driver(&mts64_parport_driver) != 0) {1043 platform_driver_unregister(&snd_mts64_driver);1044 return -EIO;1045 }1046 1047 if (device_count == 0) {1048 snd_mts64_unregister_all();1049 return -ENODEV;1050 }1051 1052 return 0;1053}1054 1055static void __exit snd_mts64_module_exit(void)1056{1057 snd_mts64_unregister_all();1058}1059 1060module_init(snd_mts64_module_init);1061module_exit(snd_mts64_module_exit);1062