Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  Copyright (c) by Uros Bizjak <uros@kss-loka.si>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *                   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Routines for OPL2/OPL3/OPL4 control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/nospec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <sound/opl3.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <sound/asound_fm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "opl3_voice.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #if IS_ENABLED(CONFIG_SND_SEQUENCER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #define OPL3_SUPPORT_SYNTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *    There is 18 possible 2 OP voices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *      (9 in the left and 9 in the right).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *      The first OP is the modulator and 2nd is the carrier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  *      The first three voices in the both sides may be connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *      with another voice to a 4 OP voice. For example voice 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *      can be connected with voice 3. The operators of voice 3 are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  *      used as operators 3 and 4 of the new 4 OP voice.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *      In this case the 2 OP voice number 0 is the 'first half' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  *      voice 3 is the second.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  *    Register offset table for OPL2/3 voices,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  *    OPL2 / one OPL3 register array side only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) char snd_opl3_regmap[MAX_OPL2_VOICES][4] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /*	  OP1   OP2   OP3   OP4		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) /*	 ------------------------	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	{ 0x00, 0x03, 0x08, 0x0b },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	{ 0x01, 0x04, 0x09, 0x0c },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	{ 0x02, 0x05, 0x0a, 0x0d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	{ 0x08, 0x0b, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	{ 0x09, 0x0c, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	{ 0x0a, 0x0d, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	{ 0x10, 0x13, 0x00, 0x00 },	/* used by percussive voices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	{ 0x11, 0x14, 0x00, 0x00 },	/* if the percussive mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	{ 0x12, 0x15, 0x00, 0x00 }	/* is selected (only left reg block) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) EXPORT_SYMBOL(snd_opl3_regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * prototypes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) /* ------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * open the device exclusively
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) int snd_opl3_open(struct snd_hwdep * hw, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * ioctl for hwdep device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		   unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	struct snd_opl3 *opl3 = hw->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	if (snd_BUG_ON(!opl3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		/* get information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	case SNDRV_DM_FM_IOCTL_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			struct snd_dm_fm_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 			memset(&info, 0, sizeof(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			info.fm_mode = opl3->fm_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 			info.rhythm = opl3->rhythm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 			if (copy_to_user(argp, &info, sizeof(struct snd_dm_fm_info)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	case SNDRV_DM_FM_IOCTL_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #ifdef CONFIG_SND_OSSEMUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	case SNDRV_DM_FM_OSS_IOCTL_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		snd_opl3_reset(opl3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	case SNDRV_DM_FM_IOCTL_PLAY_NOTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #ifdef CONFIG_SND_OSSEMUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	case SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 			struct snd_dm_fm_note note;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			if (copy_from_user(&note, argp, sizeof(struct snd_dm_fm_note)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			return snd_opl3_play_note(opl3, &note);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	case SNDRV_DM_FM_IOCTL_SET_VOICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #ifdef CONFIG_SND_OSSEMUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	case SNDRV_DM_FM_OSS_IOCTL_SET_VOICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			struct snd_dm_fm_voice voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			if (copy_from_user(&voice, argp, sizeof(struct snd_dm_fm_voice)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			return snd_opl3_set_voice(opl3, &voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	case SNDRV_DM_FM_IOCTL_SET_PARAMS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #ifdef CONFIG_SND_OSSEMUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	case SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			struct snd_dm_fm_params params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 			if (copy_from_user(&params, argp, sizeof(struct snd_dm_fm_params)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			return snd_opl3_set_params(opl3, &params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	case SNDRV_DM_FM_IOCTL_SET_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #ifdef CONFIG_SND_OSSEMUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	case SNDRV_DM_FM_OSS_IOCTL_SET_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		return snd_opl3_set_mode(opl3, (int) arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	case SNDRV_DM_FM_IOCTL_SET_CONNECTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #ifdef CONFIG_SND_OSSEMUL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	case SNDRV_DM_FM_OSS_IOCTL_SET_OPL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		return snd_opl3_set_connection(opl3, (int) arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #ifdef OPL3_SUPPORT_SYNTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	case SNDRV_DM_FM_IOCTL_CLEAR_PATCHES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		snd_opl3_clear_patches(opl3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #ifdef CONFIG_SND_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	return -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  * close the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int snd_opl3_release(struct snd_hwdep * hw, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	struct snd_opl3 *opl3 = hw->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	snd_opl3_reset(opl3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #ifdef OPL3_SUPPORT_SYNTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  * write the device - load patches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		    loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	struct snd_opl3 *opl3 = hw->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	long result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	struct sbi_patch inst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	while (count >= sizeof(inst)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		unsigned char type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		if (copy_from_user(&inst, buf, sizeof(inst)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		if (!memcmp(inst.key, FM_KEY_SBI, 4) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		    !memcmp(inst.key, FM_KEY_2OP, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			type = FM_PATCH_OPL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		else if (!memcmp(inst.key, FM_KEY_4OP, 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			type = FM_PATCH_OPL3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		else /* invalid type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		err = snd_opl3_load_patch(opl3, inst.prog, inst.bank, type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 					  inst.name, inst.extension,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 					  inst.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		result += sizeof(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		count -= sizeof(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	return result > 0 ? result : err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  * Patch management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* offsets for SBI params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) #define AM_VIB		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #define KSL_LEVEL	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define ATTACK_DECAY	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define SUSTAIN_RELEASE	6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #define WAVE_SELECT	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* offset for SBI instrument */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #define CONNECTION	10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #define OFFSET_4OP	11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)  * load a patch, obviously.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)  * loaded on the given program and bank numbers with the given type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)  * (FM_PATCH_OPLx).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)  * data is the pointer of SBI record _without_ header (key and name).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)  * name is the name string of the patch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  * ext is the extension data of 7 bytes long (stored in name of SBI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  * data up to offset 25), or NULL to skip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  * return 0 if successful or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int snd_opl3_load_patch(struct snd_opl3 *opl3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 			int prog, int bank, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			const unsigned char *ext,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 			const unsigned char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	struct fm_patch *patch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	patch = snd_opl3_find_patch(opl3, prog, bank, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	if (!patch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	patch->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		patch->inst.op[i].am_vib = data[AM_VIB + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		patch->inst.op[i].ksl_level = data[KSL_LEVEL + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		patch->inst.op[i].attack_decay = data[ATTACK_DECAY + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		patch->inst.op[i].sustain_release = data[SUSTAIN_RELEASE + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		patch->inst.op[i].wave_select = data[WAVE_SELECT + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	patch->inst.feedback_connection[0] = data[CONNECTION];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	if (type == FM_PATCH_OPL3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			patch->inst.op[i+2].am_vib =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 				data[OFFSET_4OP + AM_VIB + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			patch->inst.op[i+2].ksl_level =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 				data[OFFSET_4OP + KSL_LEVEL + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			patch->inst.op[i+2].attack_decay =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 				data[OFFSET_4OP + ATTACK_DECAY + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 			patch->inst.op[i+2].sustain_release =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 				data[OFFSET_4OP + SUSTAIN_RELEASE + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 			patch->inst.op[i+2].wave_select =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 				data[OFFSET_4OP + WAVE_SELECT + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		patch->inst.feedback_connection[1] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 			data[OFFSET_4OP + CONNECTION];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	if (ext) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		patch->inst.echo_delay = ext[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		patch->inst.echo_atten = ext[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		patch->inst.chorus_spread = ext[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		patch->inst.trnsps = ext[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		patch->inst.fix_dur = ext[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		patch->inst.modes = ext[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		patch->inst.fix_key = ext[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	if (name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		strlcpy(patch->name, name, sizeof(patch->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) EXPORT_SYMBOL(snd_opl3_load_patch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)  * find a patch with the given program and bank numbers, returns its pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)  * if no matching patch is found and create_patch is set, it creates a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)  * new patch object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct fm_patch *snd_opl3_find_patch(struct snd_opl3 *opl3, int prog, int bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 				     int create_patch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	/* pretty dumb hash key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	unsigned int key = (prog + bank) % OPL3_PATCH_HASH_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	struct fm_patch *patch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	for (patch = opl3->patch_table[key]; patch; patch = patch->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		if (patch->prog == prog && patch->bank == bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 			return patch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	if (!create_patch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	patch = kzalloc(sizeof(*patch), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	if (!patch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	patch->prog = prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	patch->bank = bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	patch->next = opl3->patch_table[key];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	opl3->patch_table[key] = patch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	return patch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) EXPORT_SYMBOL(snd_opl3_find_patch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  * Clear all patches of the given OPL3 instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) void snd_opl3_clear_patches(struct snd_opl3 *opl3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	for (i = 0; i <  OPL3_PATCH_HASH_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		struct fm_patch *patch, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		for (patch = opl3->patch_table[i]; patch; patch = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 			next = patch->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			kfree(patch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	memset(opl3->patch_table, 0, sizeof(opl3->patch_table));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) #endif /* OPL3_SUPPORT_SYNTH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* ------------------------------ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) void snd_opl3_reset(struct snd_opl3 * opl3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	unsigned short opl3_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	unsigned short reg_side;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	unsigned char voice_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	int max_voices, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	max_voices = (opl3->hardware < OPL3_HW_OPL3) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		MAX_OPL2_VOICES : MAX_OPL3_VOICES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	for (i = 0; i < max_voices; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		/* Get register array side and offset of voice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		if (i < MAX_OPL2_VOICES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 			/* Left register block for voices 0 .. 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 			reg_side = OPL3_LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			voice_offset = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 			/* Right register block for voices 9 .. 17 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			reg_side = OPL3_RIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			voice_offset = i - MAX_OPL2_VOICES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 1 volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 2 volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		opl3->command(opl3, opl3_reg, 0x00);	/* Note off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	opl3->max_voices = MAX_OPL2_VOICES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	opl3->fm_mode = SNDRV_DM_FM_MODE_OPL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00);	/* Melodic mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	opl3->rhythm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) EXPORT_SYMBOL(snd_opl3_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	unsigned short reg_side;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	unsigned char voice_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	unsigned short opl3_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	unsigned char reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	/* Voices 0 -  8 in OPL2 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	/* Voices 0 - 17 in OPL3 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	if (note->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 			    MAX_OPL3_VOICES : MAX_OPL2_VOICES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	/* Get register array side and offset of voice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	if (note->voice < MAX_OPL2_VOICES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		/* Left register block for voices 0 .. 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		reg_side = OPL3_LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		voice_offset = note->voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		/* Right register block for voices 9 .. 17 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		reg_side = OPL3_RIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		voice_offset = note->voice - MAX_OPL2_VOICES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	/* Set lower 8 bits of note frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	reg_val = (unsigned char) note->fnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	opl3->command(opl3, opl3_reg, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	reg_val = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	/* Set output sound flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	if (note->key_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		reg_val |= OPL3_KEYON_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	/* Set octave */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	reg_val |= (note->octave << 2) & OPL3_BLOCKNUM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	/* Set higher 2 bits of note frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	reg_val |= (unsigned char) (note->fnum >> 8) & OPL3_FNUM_HIGH_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	/* Set OPL3 KEYON_BLOCK register of requested voice */ 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	opl3->command(opl3, opl3_reg, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	unsigned short reg_side;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	unsigned char op_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	unsigned char voice_offset, voice_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	unsigned short opl3_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	unsigned char reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	/* Only operators 1 and 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	if (voice->op > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	/* Voices 0 -  8 in OPL2 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	/* Voices 0 - 17 in OPL3 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	if (voice->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 			     MAX_OPL3_VOICES : MAX_OPL2_VOICES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	/* Get register array side and offset of voice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	if (voice->voice < MAX_OPL2_VOICES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		/* Left register block for voices 0 .. 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		reg_side = OPL3_LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		voice_offset = voice->voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		/* Right register block for voices 9 .. 17 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		reg_side = OPL3_RIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		voice_offset = voice->voice - MAX_OPL2_VOICES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	/* Get register offset of operator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	voice_offset = array_index_nospec(voice_offset, MAX_OPL2_VOICES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	voice_op = array_index_nospec(voice->op, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	op_offset = snd_opl3_regmap[voice_offset][voice_op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	reg_val = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	/* Set amplitude modulation (tremolo) effect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	if (voice->am)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		reg_val |= OPL3_TREMOLO_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	/* Set vibrato effect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	if (voice->vibrato)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		reg_val |= OPL3_VIBRATO_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	/* Set sustaining sound phase */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	if (voice->do_sustain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		reg_val |= OPL3_SUSTAIN_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	/* Set keyboard scaling bit */ 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	if (voice->kbd_scale)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		reg_val |= OPL3_KSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	/* Set harmonic or frequency multiplier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	reg_val |= voice->harmonic & OPL3_MULTIPLE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	/* Set OPL3 AM_VIB register of requested voice/operator */ 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	opl3->command(opl3, opl3_reg, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	/* Set decreasing volume of higher notes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	reg_val = (voice->scale_level << 6) & OPL3_KSL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	/* Set output volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	reg_val |= ~voice->volume & OPL3_TOTAL_LEVEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	/* Set OPL3 KSL_LEVEL register of requested voice/operator */ 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	opl3->command(opl3, opl3_reg, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	/* Set attack phase level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	reg_val = (voice->attack << 4) & OPL3_ATTACK_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	/* Set decay phase level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	reg_val |= voice->decay & OPL3_DECAY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	/* Set OPL3 ATTACK_DECAY register of requested voice/operator */ 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	opl3->command(opl3, opl3_reg, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	/* Set sustain phase level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	reg_val = (voice->sustain << 4) & OPL3_SUSTAIN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	/* Set release phase level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	reg_val |= voice->release & OPL3_RELEASE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	/* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	opl3->command(opl3, opl3_reg, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	/* Set inter-operator feedback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	reg_val = (voice->feedback << 1) & OPL3_FEEDBACK_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	/* Set inter-operator connection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	if (voice->connection)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		reg_val |= OPL3_CONNECTION_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	/* OPL-3 only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	if (opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		if (voice->left)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 			reg_val |= OPL3_VOICE_TO_LEFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 		if (voice->right)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 			reg_val |= OPL3_VOICE_TO_RIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	/* Feedback/connection bits are applicable to voice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	opl3->command(opl3, opl3_reg, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	/* Select waveform */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	reg_val = voice->waveform & OPL3_WAVE_SELECT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	opl3->command(opl3, opl3_reg, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	unsigned char reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	reg_val = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	/* Set keyboard split method */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	if (params->kbd_split)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		reg_val |= OPL3_KEYBOARD_SPLIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	opl3->command(opl3, OPL3_LEFT | OPL3_REG_KBD_SPLIT, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	reg_val = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	/* Set amplitude modulation (tremolo) depth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	if (params->am_depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		reg_val |= OPL3_TREMOLO_DEPTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	/* Set vibrato depth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	if (params->vib_depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		reg_val |= OPL3_VIBRATO_DEPTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	/* Set percussion mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	if (params->rhythm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		reg_val |= OPL3_PERCUSSION_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		opl3->rhythm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		opl3->rhythm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	/* Play percussion instruments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	if (params->bass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		reg_val |= OPL3_BASSDRUM_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	if (params->snare)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		reg_val |= OPL3_SNAREDRUM_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	if (params->tomtom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		reg_val |= OPL3_TOMTOM_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	if (params->cymbal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 		reg_val |= OPL3_CYMBAL_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	if (params->hihat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		reg_val |= OPL3_HIHAT_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	if ((mode == SNDRV_DM_FM_MODE_OPL3) && (opl3->hardware < OPL3_HW_OPL3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	opl3->fm_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	if (opl3->hardware >= OPL3_HW_OPL3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 		opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, 0x00);	/* Clear 4-op connections */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	unsigned char reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	/* OPL-3 only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	if (opl3->fm_mode != SNDRV_DM_FM_MODE_OPL3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	reg_val = connection & (OPL3_RIGHT_4OP_0 | OPL3_RIGHT_4OP_1 | OPL3_RIGHT_4OP_2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 				OPL3_LEFT_4OP_0 | OPL3_LEFT_4OP_1 | OPL3_LEFT_4OP_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	/* Set 4-op connections */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)