0001
0002
0003
0004
0005
0006
0007 #include "opl4_local.h"
0008 #include <sound/initval.h>
0009 #include <linux/ioport.h>
0010 #include <linux/slab.h>
0011 #include <linux/init.h>
0012 #include <linux/module.h>
0013 #include <linux/io.h>
0014
0015 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
0016 MODULE_DESCRIPTION("OPL4 driver");
0017 MODULE_LICENSE("GPL");
0018
0019 static inline void snd_opl4_wait(struct snd_opl4 *opl4)
0020 {
0021 int timeout = 10;
0022 while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0)
0023 ;
0024 }
0025
0026 void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value)
0027 {
0028 snd_opl4_wait(opl4);
0029 outb(reg, opl4->pcm_port);
0030
0031 snd_opl4_wait(opl4);
0032 outb(value, opl4->pcm_port + 1);
0033 }
0034
0035 EXPORT_SYMBOL(snd_opl4_write);
0036
0037 u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg)
0038 {
0039 snd_opl4_wait(opl4);
0040 outb(reg, opl4->pcm_port);
0041
0042 snd_opl4_wait(opl4);
0043 return inb(opl4->pcm_port + 1);
0044 }
0045
0046 EXPORT_SYMBOL(snd_opl4_read);
0047
0048 void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size)
0049 {
0050 unsigned long flags;
0051 u8 memcfg;
0052
0053 spin_lock_irqsave(&opl4->reg_lock, flags);
0054
0055 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
0056 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
0057
0058 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
0059 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
0060 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
0061
0062 snd_opl4_wait(opl4);
0063 outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
0064 snd_opl4_wait(opl4);
0065 insb(opl4->pcm_port + 1, buf, size);
0066
0067 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
0068
0069 spin_unlock_irqrestore(&opl4->reg_lock, flags);
0070 }
0071
0072 EXPORT_SYMBOL(snd_opl4_read_memory);
0073
0074 void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size)
0075 {
0076 unsigned long flags;
0077 u8 memcfg;
0078
0079 spin_lock_irqsave(&opl4->reg_lock, flags);
0080
0081 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
0082 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
0083
0084 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
0085 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
0086 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
0087
0088 snd_opl4_wait(opl4);
0089 outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
0090 snd_opl4_wait(opl4);
0091 outsb(opl4->pcm_port + 1, buf, size);
0092
0093 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
0094
0095 spin_unlock_irqrestore(&opl4->reg_lock, flags);
0096 }
0097
0098 EXPORT_SYMBOL(snd_opl4_write_memory);
0099
0100 static void snd_opl4_enable_opl4(struct snd_opl4 *opl4)
0101 {
0102 outb(OPL3_REG_MODE, opl4->fm_port + 2);
0103 inb(opl4->fm_port);
0104 inb(opl4->fm_port);
0105 outb(OPL3_OPL3_ENABLE | OPL3_OPL4_ENABLE, opl4->fm_port + 3);
0106 inb(opl4->fm_port);
0107 inb(opl4->fm_port);
0108 }
0109
0110 static int snd_opl4_detect(struct snd_opl4 *opl4)
0111 {
0112 u8 id1, id2;
0113
0114 snd_opl4_enable_opl4(opl4);
0115
0116 id1 = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
0117 snd_printdd("OPL4[02]=%02x\n", id1);
0118 switch (id1 & OPL4_DEVICE_ID_MASK) {
0119 case 0x20:
0120 opl4->hardware = OPL3_HW_OPL4;
0121 break;
0122 case 0x40:
0123 opl4->hardware = OPL3_HW_OPL4_ML;
0124 break;
0125 default:
0126 return -ENODEV;
0127 }
0128
0129 snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x00);
0130 snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0xff);
0131 id1 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_FM);
0132 id2 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_PCM);
0133 snd_printdd("OPL4 id1=%02x id2=%02x\n", id1, id2);
0134 if (id1 != 0x00 || id2 != 0xff)
0135 return -ENODEV;
0136
0137 snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x3f);
0138 snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0x3f);
0139 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, 0x00);
0140 return 0;
0141 }
0142
0143 #if IS_ENABLED(CONFIG_SND_SEQUENCER)
0144 static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev)
0145 {
0146 struct snd_opl4 *opl4 = seq_dev->private_data;
0147 opl4->seq_dev = NULL;
0148 }
0149
0150 static int snd_opl4_create_seq_dev(struct snd_opl4 *opl4, int seq_device)
0151 {
0152 opl4->seq_dev_num = seq_device;
0153 if (snd_seq_device_new(opl4->card, seq_device, SNDRV_SEQ_DEV_ID_OPL4,
0154 sizeof(struct snd_opl4 *), &opl4->seq_dev) >= 0) {
0155 strcpy(opl4->seq_dev->name, "OPL4 Wavetable");
0156 *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(opl4->seq_dev) = opl4;
0157 opl4->seq_dev->private_data = opl4;
0158 opl4->seq_dev->private_free = snd_opl4_seq_dev_free;
0159 }
0160 return 0;
0161 }
0162 #endif
0163
0164 static void snd_opl4_free(struct snd_opl4 *opl4)
0165 {
0166 snd_opl4_free_proc(opl4);
0167 release_and_free_resource(opl4->res_fm_port);
0168 release_and_free_resource(opl4->res_pcm_port);
0169 kfree(opl4);
0170 }
0171
0172 static int snd_opl4_dev_free(struct snd_device *device)
0173 {
0174 struct snd_opl4 *opl4 = device->device_data;
0175 snd_opl4_free(opl4);
0176 return 0;
0177 }
0178
0179 int snd_opl4_create(struct snd_card *card,
0180 unsigned long fm_port, unsigned long pcm_port,
0181 int seq_device,
0182 struct snd_opl3 **ropl3, struct snd_opl4 **ropl4)
0183 {
0184 struct snd_opl4 *opl4;
0185 struct snd_opl3 *opl3;
0186 int err;
0187 static const struct snd_device_ops ops = {
0188 .dev_free = snd_opl4_dev_free
0189 };
0190
0191 if (ropl3)
0192 *ropl3 = NULL;
0193 if (ropl4)
0194 *ropl4 = NULL;
0195
0196 opl4 = kzalloc(sizeof(*opl4), GFP_KERNEL);
0197 if (!opl4)
0198 return -ENOMEM;
0199
0200 opl4->res_fm_port = request_region(fm_port, 8, "OPL4 FM");
0201 opl4->res_pcm_port = request_region(pcm_port, 8, "OPL4 PCM/MIX");
0202 if (!opl4->res_fm_port || !opl4->res_pcm_port) {
0203 snd_printk(KERN_ERR "opl4: can't grab ports 0x%lx, 0x%lx\n", fm_port, pcm_port);
0204 snd_opl4_free(opl4);
0205 return -EBUSY;
0206 }
0207
0208 opl4->card = card;
0209 opl4->fm_port = fm_port;
0210 opl4->pcm_port = pcm_port;
0211 spin_lock_init(&opl4->reg_lock);
0212 mutex_init(&opl4->access_mutex);
0213
0214 err = snd_opl4_detect(opl4);
0215 if (err < 0) {
0216 snd_opl4_free(opl4);
0217 snd_printd("OPL4 chip not detected at %#lx/%#lx\n", fm_port, pcm_port);
0218 return err;
0219 }
0220
0221 err = snd_device_new(card, SNDRV_DEV_CODEC, opl4, &ops);
0222 if (err < 0) {
0223 snd_opl4_free(opl4);
0224 return err;
0225 }
0226
0227 err = snd_opl3_create(card, fm_port, fm_port + 2, opl4->hardware, 1, &opl3);
0228 if (err < 0) {
0229 snd_device_free(card, opl4);
0230 return err;
0231 }
0232
0233
0234 snd_opl4_enable_opl4(opl4);
0235
0236 snd_opl4_create_mixer(opl4);
0237 snd_opl4_create_proc(opl4);
0238
0239 #if IS_ENABLED(CONFIG_SND_SEQUENCER)
0240 opl4->seq_client = -1;
0241 if (opl4->hardware < OPL3_HW_OPL4_ML)
0242 snd_opl4_create_seq_dev(opl4, seq_device);
0243 #endif
0244
0245 if (ropl3)
0246 *ropl3 = opl3;
0247 if (ropl4)
0248 *ropl4 = opl4;
0249 return 0;
0250 }
0251
0252 EXPORT_SYMBOL(snd_opl4_create);