diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 10:16:28 +1100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-02-01 10:16:28 +1100 |
commit | e1a9c9872dd004617555dff079b357a6ffd945e9 (patch) | |
tree | c34779e59712ff345f8e4ee97e74086a85b34974 /sound/drivers/opl3/opl3_oss.c | |
parent | fcc3ff4f9d695a80dc6e6058e0d631a3026ed4c3 (diff) | |
parent | 2ecba4ffbbc6c85fce8c3878514be415edace413 (diff) | |
download | talos-obmc-linux-e1a9c9872dd004617555dff079b357a6ffd945e9.tar.gz talos-obmc-linux-e1a9c9872dd004617555dff079b357a6ffd945e9.zip |
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa
* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa: (299 commits)
[ALSA] version 1.0.16rc2
[ALSA] hda: fix Mic in as output
[ALSA] emu10k1 - Another EMU0404 Board ID
[ALSA] emu10k1 - Fix kthread handling at resume
[ALSA] emu10k1: General cleanup, add new locks, fix alsa bug#3501, kernel bug#9304.
[ALSA] emu10k1 - Use enum for emu_model types
[ALSA] emu10k1 - Don't create emu1010 controls for non-emu boards
[ALSA] emu10k1 - 1616(M) cardbus improvements
[ALSA] snd:emu10k1: E-Mu updates. Fixes to firmware loading and support for 0404.
[ALSA] emu10k1: Add comments regarding E-Mu ins and outs.
[ALSA] oxygen: revert SPI clock frequency change for AK4396/WM8785
[ALSA] es1938 - improve capture hw pointer reads
[ALSA] HDA-Intel - Add support for Intel SCH
[ALSA] hda: Add GPIO mute support to STAC9205
[ALSA] hda-codec - Add Dell T3400 support
[ALSA] hda-codec - Add model for HP DV9553EG laptop
[ALSA] hda-codec - Control SPDIF as slave
[ALSA] hda_intel: ALSA HD Audio patch for Intel ICH10 DeviceID's
[ALSA] Fix Oops with PCM OSS sync
[ALSA] hda-codec - Add speaker automute to ALC262 HP models
...
Diffstat (limited to 'sound/drivers/opl3/opl3_oss.c')
-rw-r--r-- | sound/drivers/opl3/opl3_oss.c | 135 |
1 files changed, 27 insertions, 108 deletions
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index 5fd3a4c95626..239347f26154 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -195,17 +195,6 @@ static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg) /* load patch */ -/* offsets for SBI params */ -#define AM_VIB 0 -#define KSL_LEVEL 2 -#define ATTACK_DECAY 4 -#define SUSTAIN_RELEASE 6 -#define WAVE_SELECT 8 - -/* offset for SBI instrument */ -#define CONNECTION 10 -#define OFFSET_4OP 11 - /* from sound_config.h */ #define SBFM_MAXINSTR 256 @@ -213,112 +202,42 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count) { struct snd_opl3 *opl3; - int err = -EINVAL; + struct sbi_instrument sbi; + char name[32]; + int err, type; snd_assert(arg != NULL, return -ENXIO); opl3 = arg->private_data; - if ((format == FM_PATCH) || (format == OPL3_PATCH)) { - struct sbi_instrument sbi; + if (format == FM_PATCH) + type = FM_PATCH_OPL2; + else if (format == OPL3_PATCH) + type = FM_PATCH_OPL3; + else + return -EINVAL; - size_t size; - struct snd_seq_instr_header *put; - struct snd_seq_instr_data *data; - struct fm_xinstrument *xinstr; + if (count < (int)sizeof(sbi)) { + snd_printk("FM Error: Patch record too short\n"); + return -EINVAL; + } + if (copy_from_user(&sbi, buf, sizeof(sbi))) + return -EFAULT; - struct snd_seq_event ev; - int i; + if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { + snd_printk("FM Error: Invalid instrument number %d\n", + sbi.channel); + return -EINVAL; + } - mm_segment_t fs; + memset(name, 0, sizeof(name)); + sprintf(name, "Chan%d", sbi.channel); - if (count < (int)sizeof(sbi)) { - snd_printk("FM Error: Patch record too short\n"); - return -EINVAL; - } - if (copy_from_user(&sbi, buf, sizeof(sbi))) - return -EFAULT; + err = snd_opl3_load_patch(opl3, sbi.channel, 127, type, name, NULL, + sbi.operators); + if (err < 0) + return err; - if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { - snd_printk("FM Error: Invalid instrument number %d\n", sbi.channel); - return -EINVAL; - } - - size = sizeof(*put) + sizeof(struct fm_xinstrument); - put = kzalloc(size, GFP_KERNEL); - if (put == NULL) - return -ENOMEM; - /* build header */ - data = &put->data; - data->type = SNDRV_SEQ_INSTR_ATYPE_DATA; - strcpy(data->data.format, SNDRV_SEQ_INSTR_ID_OPL2_3); - /* build data section */ - xinstr = (struct fm_xinstrument *)(data + 1); - xinstr->stype = FM_STRU_INSTR; - - for (i = 0; i < 2; i++) { - xinstr->op[i].am_vib = sbi.operators[AM_VIB + i]; - xinstr->op[i].ksl_level = sbi.operators[KSL_LEVEL + i]; - xinstr->op[i].attack_decay = sbi.operators[ATTACK_DECAY + i]; - xinstr->op[i].sustain_release = sbi.operators[SUSTAIN_RELEASE + i]; - xinstr->op[i].wave_select = sbi.operators[WAVE_SELECT + i]; - } - xinstr->feedback_connection[0] = sbi.operators[CONNECTION]; - - if (format == OPL3_PATCH) { - xinstr->type = FM_PATCH_OPL3; - for (i = 0; i < 2; i++) { - xinstr->op[i+2].am_vib = sbi.operators[OFFSET_4OP + AM_VIB + i]; - xinstr->op[i+2].ksl_level = sbi.operators[OFFSET_4OP + KSL_LEVEL + i]; - xinstr->op[i+2].attack_decay = sbi.operators[OFFSET_4OP + ATTACK_DECAY + i]; - xinstr->op[i+2].sustain_release = sbi.operators[OFFSET_4OP + SUSTAIN_RELEASE + i]; - xinstr->op[i+2].wave_select = sbi.operators[OFFSET_4OP + WAVE_SELECT + i]; - } - xinstr->feedback_connection[1] = sbi.operators[OFFSET_4OP + CONNECTION]; - } else { - xinstr->type = FM_PATCH_OPL2; - } - - put->id.instr.std = SNDRV_SEQ_INSTR_TYPE2_OPL2_3; - put->id.instr.bank = 127; - put->id.instr.prg = sbi.channel; - put->cmd = SNDRV_SEQ_INSTR_PUT_CMD_CREATE; - - memset (&ev, 0, sizeof(ev)); - ev.source.client = SNDRV_SEQ_CLIENT_OSS; - ev.dest = arg->addr; - - ev.flags = SNDRV_SEQ_EVENT_LENGTH_VARUSR; - ev.queue = SNDRV_SEQ_QUEUE_DIRECT; - - fs = snd_enter_user(); - __again: - ev.type = SNDRV_SEQ_EVENT_INSTR_PUT; - ev.data.ext.len = size; - ev.data.ext.ptr = put; - - err = snd_seq_instr_event(&opl3->fm_ops, opl3->ilist, &ev, - opl3->seq_client, 0, 0); - if (err == -EBUSY) { - struct snd_seq_instr_header remove; - - memset (&remove, 0, sizeof(remove)); - remove.cmd = SNDRV_SEQ_INSTR_FREE_CMD_SINGLE; - remove.id.instr = put->id.instr; - - /* remove instrument */ - ev.type = SNDRV_SEQ_EVENT_INSTR_FREE; - ev.data.ext.len = sizeof(remove); - ev.data.ext.ptr = &remove; - - snd_seq_instr_event(&opl3->fm_ops, opl3->ilist, &ev, - opl3->seq_client, 0, 0); - goto __again; - } - snd_leave_user(fs); - - kfree(put); - } - return err; + return sizeof(sbi); } /* ioctl */ |