cregit-Linux how code gets into the kernel

Release 4.11 sound/pci/ca0106/ca_midi.c

Directory: sound/pci/ca0106
/* 
 *  Copyright 10/16/2005 Tilman Kranz <tilde@tk-sls.de>
 *  Creative Audio MIDI, for the CA0106 Driver
 *  Version: 0.0.1
 *
 *  Changelog:
 *    Implementation is based on mpu401 and emu10k1x and
 *    tested with ca0106.
 *    mpu401: Copyright (c) by Jaroslav Kysela <perex@perex.cz>
 *    emu10k1x: Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 *
 */

#include <linux/spinlock.h>
#include <sound/core.h>
#include <sound/rawmidi.h>

#include "ca_midi.h"


#define ca_midi_write_data(midi, data)	midi->write(midi, data, 0)

#define ca_midi_write_cmd(midi, data)	midi->write(midi, data, 1)

#define ca_midi_read_data(midi)		midi->read(midi, 0)

#define ca_midi_read_stat(midi)		midi->read(midi, 1)

#define ca_midi_input_avail(midi)	(!(ca_midi_read_stat(midi) & midi->input_avail))

#define ca_midi_output_ready(midi)	(!(ca_midi_read_stat(midi) & midi->output_ready))


static void ca_midi_clear_rx(struct snd_ca_midi *midi) { int timeout = 100000; for (; timeout > 0 && ca_midi_input_avail(midi); timeout--) ca_midi_read_data(midi); #ifdef CONFIG_SND_DEBUG if (timeout <= 0) pr_err("ca_midi_clear_rx: timeout (status = 0x%x)\n", ca_midi_read_stat(midi)); #endif }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton5494.74%133.33%
Takashi Iwai35.26%266.67%
Total57100.00%3100.00%


static void ca_midi_interrupt(struct snd_ca_midi *midi, unsigned int status) { unsigned char byte; if (midi->rmidi == NULL) { midi->interrupt_disable(midi,midi->tx_enable | midi->rx_enable); return; } spin_lock(&midi->input_lock); if ((status & midi->ipr_rx) && ca_midi_input_avail(midi)) { if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { ca_midi_clear_rx(midi); } else { byte = ca_midi_read_data(midi); if(midi->substream_input) snd_rawmidi_receive(midi->substream_input, &byte, 1); } } spin_unlock(&midi->input_lock); spin_lock(&midi->output_lock); if ((status & midi->ipr_tx) && ca_midi_output_ready(midi)) { if (midi->substream_output && snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { ca_midi_write_data(midi, byte); } else { midi->interrupt_disable(midi,midi->tx_enable); } } spin_unlock(&midi->output_lock); }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton19899.00%266.67%
Takashi Iwai21.00%133.33%
Total200100.00%3100.00%


static void ca_midi_cmd(struct snd_ca_midi *midi, unsigned char cmd, int ack) { unsigned long flags; int timeout, ok; spin_lock_irqsave(&midi->input_lock, flags); ca_midi_write_data(midi, 0x00); /* ca_midi_clear_rx(midi); */ ca_midi_write_cmd(midi, cmd); if (ack) { ok = 0; timeout = 10000; while (!ok && timeout-- > 0) { if (ca_midi_input_avail(midi)) { if (ca_midi_read_data(midi) == midi->ack) ok = 1; } } if (!ok && ca_midi_read_data(midi) == midi->ack) ok = 1; } else { ok = 1; } spin_unlock_irqrestore(&midi->input_lock, flags); if (!ok) pr_err("ca_midi_cmd: 0x%x failed at 0x%x (status = 0x%x, data = 0x%x)!!!\n", cmd, midi->get_dev_id_port(midi->dev_id), ca_midi_read_stat(midi), ca_midi_read_data(midi)); }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton16598.21%133.33%
Takashi Iwai31.79%266.67%
Total168100.00%3100.00%


static int ca_midi_input_open(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->midi_mode |= CA_MIDI_MODE_INPUT; midi->substream_input = substream; if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) { spin_unlock_irqrestore(&midi->open_lock, flags); ca_midi_cmd(midi, midi->reset, 1); ca_midi_cmd(midi, midi->enter_uart, 1); } else { spin_unlock_irqrestore(&midi->open_lock, flags); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton10786.99%133.33%
Takashi Iwai1613.01%266.67%
Total123100.00%3100.00%


static int ca_midi_output_open(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->midi_mode |= CA_MIDI_MODE_OUTPUT; midi->substream_output = substream; if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { spin_unlock_irqrestore(&midi->open_lock, flags); ca_midi_cmd(midi, midi->reset, 1); ca_midi_cmd(midi, midi->enter_uart, 1); } else { spin_unlock_irqrestore(&midi->open_lock, flags); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton10786.99%133.33%
Takashi Iwai1613.01%266.67%
Total123100.00%3100.00%


static int ca_midi_input_close(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->interrupt_disable(midi,midi->rx_enable); midi->midi_mode &= ~CA_MIDI_MODE_INPUT; midi->substream_input = NULL; if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT)) { spin_unlock_irqrestore(&midi->open_lock, flags); ca_midi_cmd(midi, midi->reset, 0); } else { spin_unlock_irqrestore(&midi->open_lock, flags); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton10887.10%133.33%
Takashi Iwai1612.90%266.67%
Total124100.00%3100.00%


static int ca_midi_output_close(struct snd_rawmidi_substream *substream) { struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return -ENXIO; spin_lock_irqsave(&midi->open_lock, flags); midi->interrupt_disable(midi,midi->tx_enable); midi->midi_mode &= ~CA_MIDI_MODE_OUTPUT; midi->substream_output = NULL; if (!(midi->midi_mode & CA_MIDI_MODE_INPUT)) { spin_unlock_irqrestore(&midi->open_lock, flags); ca_midi_cmd(midi, midi->reset, 0); } else { spin_unlock_irqrestore(&midi->open_lock, flags); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton10887.10%133.33%
Takashi Iwai1612.90%266.67%
Total124100.00%3100.00%


static void ca_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) { struct snd_ca_midi *midi = substream->rmidi->private_data; if (snd_BUG_ON(!midi->dev_id)) return; if (up) { midi->interrupt_enable(midi,midi->rx_enable); } else { midi->interrupt_disable(midi, midi->rx_enable); } }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton5480.60%133.33%
Takashi Iwai1319.40%266.67%
Total67100.00%3100.00%


static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) { struct snd_ca_midi *midi = substream->rmidi->private_data; unsigned long flags; if (snd_BUG_ON(!midi->dev_id)) return; if (up) { int max = 4; unsigned char byte; spin_lock_irqsave(&midi->output_lock, flags); /* try to send some amount of bytes here before interrupts */ while (max > 0) { if (ca_midi_output_ready(midi)) { if (!(midi->midi_mode & CA_MIDI_MODE_OUTPUT) || snd_rawmidi_transmit(substream, &byte, 1) != 1) { /* no more data */ spin_unlock_irqrestore(&midi->output_lock, flags); return; } ca_midi_write_data(midi, byte); max--; } else { break; } } spin_unlock_irqrestore(&midi->output_lock, flags); midi->interrupt_enable(midi,midi->tx_enable); } else { midi->interrupt_disable(midi,midi->tx_enable); } }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton15692.31%133.33%
Takashi Iwai137.69%266.67%
Total169100.00%3100.00%

static const struct snd_rawmidi_ops ca_midi_output = { .open = ca_midi_output_open, .close = ca_midi_output_close, .trigger = ca_midi_output_trigger, }; static const struct snd_rawmidi_ops ca_midi_input = { .open = ca_midi_input_open, .close = ca_midi_input_close, .trigger = ca_midi_input_trigger, };
static void ca_midi_free(struct snd_ca_midi *midi) { midi->interrupt = NULL; midi->interrupt_enable = NULL; midi->interrupt_disable = NULL; midi->read = NULL; midi->write = NULL; midi->get_dev_id_card = NULL; midi->get_dev_id_port = NULL; midi->rmidi = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton5796.61%266.67%
Takashi Iwai23.39%133.33%
Total59100.00%3100.00%


static void ca_rmidi_free(struct snd_rawmidi *rmidi) { ca_midi_free(rmidi->private_data); }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton1688.89%150.00%
Takashi Iwai211.11%150.00%
Total18100.00%2100.00%


int ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name) { struct snd_rawmidi *rmidi; int err; if ((err = snd_rawmidi_new(midi->get_dev_id_card(midi->dev_id), name, device, 1, 1, &rmidi)) < 0) return err; midi->dev_id = dev_id; midi->interrupt = ca_midi_interrupt; spin_lock_init(&midi->open_lock); spin_lock_init(&midi->input_lock); spin_lock_init(&midi->output_lock); strcpy(rmidi->name, name); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &ca_midi_output); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &ca_midi_input); rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; rmidi->private_data = midi; rmidi->private_free = ca_rmidi_free; midi->rmidi = rmidi; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton15597.48%150.00%
Takashi Iwai42.52%150.00%
Total159100.00%2100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
James Courtier-Dutton138392.45%228.57%
Takashi Iwai1127.49%457.14%
Jaroslav Kysela10.07%114.29%
Total1496100.00%7100.00%
Directory: sound/pci/ca0106
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.