/*
* ALSA Driver for Ego Systems Inc. (ESI) Miditerminal 4140
* Copyright (c) 2006 by Matthias König <mk@phasorlab.de>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/parport.h>
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/rawmidi.h>
#include <sound/control.h>
#define CARD_NAME "Miditerminal 4140"
#define DRIVER_NAME "MTS64"
#define PLATFORM_DRIVER "snd_mts64"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static struct platform_device *platform_devices[SNDRV_CARDS];
static int device_count;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
MODULE_AUTHOR("Matthias Koenig <mk@phasorlab.de>");
MODULE_DESCRIPTION("ESI Miditerminal 4140");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{ESI,Miditerminal 4140}}");
/*********************************************************************
* Chip specific
*********************************************************************/
#define MTS64_NUM_INPUT_PORTS 5
#define MTS64_NUM_OUTPUT_PORTS 4
#define MTS64_SMPTE_SUBSTREAM 4
struct mts64 {
spinlock_t lock;
struct snd_card *card;
struct snd_rawmidi *rmidi;
struct pardevice *pardev;
int open_count;
int current_midi_output_port;
int current_midi_input_port;
u8 mode[MTS64_NUM_INPUT_PORTS];
struct snd_rawmidi_substream *midi_input_substream[MTS64_NUM_INPUT_PORTS];
int smpte_switch;
u8 time[4]; /* [0]=hh, [1]=mm, [2]=ss, [3]=ff */
u8 fps;
};
static int snd_mts64_free(struct mts64 *mts)
{
kfree(mts);
return 0;
}
static int snd_mts64_create(struct snd_card *card,
struct pardevice *pardev,
struct mts64 **rchip)
{
struct mts64 *mts;
*rchip = NULL;
mts = kzalloc(sizeof(struct mts64), GFP_KERNEL);
if (mts == NULL)
return -ENOMEM;
/* Init chip specific data */
spin_lock_init(&mts->lock);
mts->card = card;
mts->pardev = pardev;
mts->current_midi_output_port = -1;
mts->current_midi_input_port = -1;
*rchip = mts;
return 0;
}
/*********************************************************************
* HW register related constants
*********************************************************************/
/* Status Bits */
#define MTS64_STAT_BSY 0x80
#define MTS64_STAT_BIT_SET 0x20 /* readout process, bit is set */
#define MTS64_STAT_PORT 0x10 /* read byte is a port number */
/* Control Bits */
#define MTS64_CTL_READOUT 0x08 /* enable readout */
#define MTS64_CTL_WRITE_CMD 0x06
#define MTS64_CTL_WRITE_DATA 0x02
#define MTS64_CTL_STROBE 0x01
/* Command */
#define MTS64_CMD_RESET 0xfe
#define MTS64_CMD_PROBE 0x8f /* Used in probing procedure */
#define MTS64_CMD_SMPTE_SET_TIME 0xe8
#define MTS64_CMD_SMPTE_SET_FPS 0xee
#define MTS64_CMD_SMPTE_STOP 0xef
#define MTS64_CMD_SMPTE_FPS_24 0xe3
#define MTS64_CMD_SMPTE_FPS_25 0xe2
#define MTS64_CMD_SMPTE_FPS_2997 0xe4
#define MTS64_CMD_SMPTE_FPS_30D 0xe1
#define MTS64_CMD_SMPTE_FPS_30 0xe0
#define MTS64_CMD_COM_OPEN 0xf8 /* setting the communication mode */
#define MTS64_CMD_COM_CLOSE1 0xff /* clearing communication mode */
#define MTS64_CMD_COM_CLOSE2 0xf5
/*********************************************************************
* Hardware specific functions
*********************************************************************/
static void mts64_enable_readout(struct parport *p);
static void mts64_disable_readout(struct parport *p);
static int mts64_device_ready(struct parport *p);
static int mts64_device_init(struct parport *p);
static int mts64_device_open(struct mts64 *mts);
static int mts64_device_close(struct mts64 *mts);
static u8 mts64_map_midi_input(u8 c);
static int mts64_probe(struct parport *p);
static u16 mts64_read(struct parport *p);
static u8 mts64_read_char(struct parport *p);
static void mts64_smpte_start(struct parport *p,
u8 hours, u8 minutes,
u8 seconds,