// SPDX-License-Identifier: GPL-2.0-or-later
/*
* ALSA sequencer event conversion between UMP and legacy clients
*/
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <sound/core.h>
#include <sound/ump.h>
#include <sound/ump_msg.h>
#include "seq_ump_convert.h"
/*
* Upgrade / downgrade value bits
*/
static u8 downscale_32_to_7bit(u32 src)
{
return src >> 25;
}
static u16 downscale_32_to_14bit(u32 src)
{
return src >> 18;
}
static u8 downscale_16_to_7bit(u16 src)
{
return src >> 9;
}
static u16 upscale_7_to_16bit(u8 src)
{
u16 val, repeat;
val = (u16)src << 9;
if (src <= 0x40)
return val;
repeat = src & 0x3f;
return val | (repeat << 3) | (repeat >> 3);
}
static u32 upscale_7_to_32bit(u8 src)
{
u32 val, repeat;
val = src << 25;
if (src <= 0x40)
return val;
repeat = src & 0x3f;
return val | (repeat << 19) | (repeat << 13) |
(repeat << 7) | (repeat << 1) | (repeat >> 5);
}
static u32 upscale_14_to_32bit(u16 src)
{
u32 val, repeat;
val = src << 18;
if (src <= 0x2000)
return val;
repeat = src & 0x1fff;
return val | (repeat << 5) | (repeat >> 8);
}
static unsigned char get_ump_group(struct snd_seq_client_port *port)
{
return port->ump_group ? (port->ump_group - 1) : 0;
}
/* create a UMP header */
#define make_raw_ump(port, type) \
ump_compose(type, get_ump_group(port), 0, 0)
/*
* UMP -> MIDI1 sequencer event
*/
/* MIDI 1.0 CVM */
/* encode note event */
static void ump_midi1_to_note_ev(const union snd_ump_midi1_msg *val,
struct snd_seq_event *ev)
{
ev->data.note.channel = val->note.channel;
ev->data.note.note = val->note.note;
ev->data.note.velocity = val->note.velocity;
}
/* encode one parameter controls */
static void ump_midi1_to_ctrl_ev(const union snd_ump_midi1_msg *val,
struct snd_seq_event *ev)
{
ev->data.control.channel = val->caf.channel;
ev->data.control.value = val->caf.data;
}
/* encode pitch wheel change */
static void ump_midi1_to_pitchbend_ev(const union snd_ump_midi1_msg *val,
struct snd_seq_event *ev)
{
ev->data.control.channel = val->pb.channel;
ev->data.control.value = (val->pb.data_msb << 7) | val->pb.data_lsb;