cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

opl3_lib.c (13133B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
      4 *                   Hannu Savolainen 1993-1996,
      5 *                   Rob Hooft
      6 *                   
      7 *  Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)
      8 *
      9 *  Most if code is ported from OSS/Lite.
     10 */
     11
     12#include <sound/opl3.h>
     13#include <linux/io.h>
     14#include <linux/delay.h>
     15#include <linux/module.h>
     16#include <linux/init.h>
     17#include <linux/slab.h>
     18#include <linux/ioport.h>
     19#include <sound/minors.h>
     20#include "opl3_voice.h"
     21
     22MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Hannu Savolainen 1993-1996, Rob Hooft");
     23MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)");
     24MODULE_LICENSE("GPL");
     25
     26static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val)
     27{
     28	unsigned long flags;
     29	unsigned long port;
     30
     31	/*
     32	 * The original 2-OP synth requires a quite long delay
     33	 * after writing to a register.
     34	 */
     35
     36	port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port;
     37
     38	spin_lock_irqsave(&opl3->reg_lock, flags);
     39
     40	outb((unsigned char) cmd, port);
     41	udelay(10);
     42
     43	outb((unsigned char) val, port + 1);
     44	udelay(30);
     45
     46	spin_unlock_irqrestore(&opl3->reg_lock, flags);
     47}
     48
     49static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val)
     50{
     51	unsigned long flags;
     52	unsigned long port;
     53
     54	/*
     55	 * The OPL-3 survives with just two INBs
     56	 * after writing to a register.
     57	 */
     58
     59	port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port;
     60
     61	spin_lock_irqsave(&opl3->reg_lock, flags);
     62
     63	outb((unsigned char) cmd, port);
     64	inb(opl3->l_port);
     65	inb(opl3->l_port);
     66
     67	outb((unsigned char) val, port + 1);
     68	inb(opl3->l_port);
     69	inb(opl3->l_port);
     70
     71	spin_unlock_irqrestore(&opl3->reg_lock, flags);
     72}
     73
     74static int snd_opl3_detect(struct snd_opl3 * opl3)
     75{
     76	/*
     77	 * This function returns 1 if the FM chip is present at the given I/O port
     78	 * The detection algorithm plays with the timer built in the FM chip and
     79	 * looks for a change in the status register.
     80	 *
     81	 * Note! The timers of the FM chip are not connected to AdLib (and compatible)
     82	 * boards.
     83	 *
     84	 * Note2! The chip is initialized if detected.
     85	 */
     86
     87	unsigned char stat1, stat2, signature;
     88
     89	/* Reset timers 1 and 2 */
     90	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK);
     91	/* Reset the IRQ of the FM chip */
     92	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
     93	signature = stat1 = inb(opl3->l_port);	/* Status register */
     94	if ((stat1 & 0xe0) != 0x00) {	/* Should be 0x00 */
     95		snd_printd("OPL3: stat1 = 0x%x\n", stat1);
     96		return -ENODEV;
     97	}
     98	/* Set timer1 to 0xff */
     99	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 0xff);
    100	/* Unmask and start timer 1 */
    101	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER2_MASK | OPL3_TIMER1_START);
    102	/* Now we have to delay at least 80us */
    103	udelay(200);
    104	/* Read status after timers have expired */
    105	stat2 = inb(opl3->l_port);
    106	/* Stop the timers */
    107	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK);
    108	/* Reset the IRQ of the FM chip */
    109	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
    110	if ((stat2 & 0xe0) != 0xc0) {	/* There is no YM3812 */
    111		snd_printd("OPL3: stat2 = 0x%x\n", stat2);
    112		return -ENODEV;
    113	}
    114
    115	/* If the toplevel code knows exactly the type of chip, don't try
    116	   to detect it. */
    117	if (opl3->hardware != OPL3_HW_AUTO)
    118		return 0;
    119
    120	/* There is a FM chip on this address. Detect the type (OPL2 to OPL4) */
    121	if (signature == 0x06) {	/* OPL2 */
    122		opl3->hardware = OPL3_HW_OPL2;
    123	} else {
    124		/*
    125		 * If we had an OPL4 chip, opl3->hardware would have been set
    126		 * by the OPL4 driver; so we can assume OPL3 here.
    127		 */
    128		if (snd_BUG_ON(!opl3->r_port))
    129			return -ENODEV;
    130		opl3->hardware = OPL3_HW_OPL3;
    131	}
    132	return 0;
    133}
    134
    135/*
    136 *  AdLib timers
    137 */
    138
    139/*
    140 *  Timer 1 - 80us
    141 */
    142
    143static int snd_opl3_timer1_start(struct snd_timer * timer)
    144{
    145	unsigned long flags;
    146	unsigned char tmp;
    147	unsigned int ticks;
    148	struct snd_opl3 *opl3;
    149
    150	opl3 = snd_timer_chip(timer);
    151	spin_lock_irqsave(&opl3->timer_lock, flags);
    152	ticks = timer->sticks;
    153	tmp = (opl3->timer_enable | OPL3_TIMER1_START) & ~OPL3_TIMER1_MASK;
    154	opl3->timer_enable = tmp;
    155	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 256 - ticks);	/* timer 1 count */
    156	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp);	/* enable timer 1 IRQ */
    157	spin_unlock_irqrestore(&opl3->timer_lock, flags);
    158	return 0;
    159}
    160
    161static int snd_opl3_timer1_stop(struct snd_timer * timer)
    162{
    163	unsigned long flags;
    164	unsigned char tmp;
    165	struct snd_opl3 *opl3;
    166
    167	opl3 = snd_timer_chip(timer);
    168	spin_lock_irqsave(&opl3->timer_lock, flags);
    169	tmp = (opl3->timer_enable | OPL3_TIMER1_MASK) & ~OPL3_TIMER1_START;
    170	opl3->timer_enable = tmp;
    171	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp);	/* disable timer #1 */
    172	spin_unlock_irqrestore(&opl3->timer_lock, flags);
    173	return 0;
    174}
    175
    176/*
    177 *  Timer 2 - 320us
    178 */
    179
    180static int snd_opl3_timer2_start(struct snd_timer * timer)
    181{
    182	unsigned long flags;
    183	unsigned char tmp;
    184	unsigned int ticks;
    185	struct snd_opl3 *opl3;
    186
    187	opl3 = snd_timer_chip(timer);
    188	spin_lock_irqsave(&opl3->timer_lock, flags);
    189	ticks = timer->sticks;
    190	tmp = (opl3->timer_enable | OPL3_TIMER2_START) & ~OPL3_TIMER2_MASK;
    191	opl3->timer_enable = tmp;
    192	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER2, 256 - ticks);	/* timer 1 count */
    193	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp);	/* enable timer 1 IRQ */
    194	spin_unlock_irqrestore(&opl3->timer_lock, flags);
    195	return 0;
    196}
    197
    198static int snd_opl3_timer2_stop(struct snd_timer * timer)
    199{
    200	unsigned long flags;
    201	unsigned char tmp;
    202	struct snd_opl3 *opl3;
    203
    204	opl3 = snd_timer_chip(timer);
    205	spin_lock_irqsave(&opl3->timer_lock, flags);
    206	tmp = (opl3->timer_enable | OPL3_TIMER2_MASK) & ~OPL3_TIMER2_START;
    207	opl3->timer_enable = tmp;
    208	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp);	/* disable timer #1 */
    209	spin_unlock_irqrestore(&opl3->timer_lock, flags);
    210	return 0;
    211}
    212
    213/*
    214
    215 */
    216
    217static const struct snd_timer_hardware snd_opl3_timer1 =
    218{
    219	.flags =	SNDRV_TIMER_HW_STOP,
    220	.resolution =	80000,
    221	.ticks =	256,
    222	.start =	snd_opl3_timer1_start,
    223	.stop =		snd_opl3_timer1_stop,
    224};
    225
    226static const struct snd_timer_hardware snd_opl3_timer2 =
    227{
    228	.flags =	SNDRV_TIMER_HW_STOP,
    229	.resolution =	320000,
    230	.ticks =	256,
    231	.start =	snd_opl3_timer2_start,
    232	.stop =		snd_opl3_timer2_stop,
    233};
    234
    235static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no)
    236{
    237	struct snd_timer *timer = NULL;
    238	struct snd_timer_id tid;
    239	int err;
    240
    241	tid.dev_class = SNDRV_TIMER_CLASS_CARD;
    242	tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
    243	tid.card = opl3->card->number;
    244	tid.device = timer_no;
    245	tid.subdevice = 0;
    246	err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer);
    247	if (err >= 0) {
    248		strcpy(timer->name, "AdLib timer #1");
    249		timer->private_data = opl3;
    250		timer->hw = snd_opl3_timer1;
    251	}
    252	opl3->timer1 = timer;
    253	return err;
    254}
    255
    256static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no)
    257{
    258	struct snd_timer *timer = NULL;
    259	struct snd_timer_id tid;
    260	int err;
    261
    262	tid.dev_class = SNDRV_TIMER_CLASS_CARD;
    263	tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
    264	tid.card = opl3->card->number;
    265	tid.device = timer_no;
    266	tid.subdevice = 0;
    267	err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer);
    268	if (err >= 0) {
    269		strcpy(timer->name, "AdLib timer #2");
    270		timer->private_data = opl3;
    271		timer->hw = snd_opl3_timer2;
    272	}
    273	opl3->timer2 = timer;
    274	return err;
    275}
    276
    277/*
    278
    279 */
    280
    281void snd_opl3_interrupt(struct snd_hwdep * hw)
    282{
    283	unsigned char status;
    284	struct snd_opl3 *opl3;
    285	struct snd_timer *timer;
    286
    287	if (hw == NULL)
    288		return;
    289
    290	opl3 = hw->private_data;
    291	status = inb(opl3->l_port);
    292#if 0
    293	snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status);
    294#endif
    295	if (!(status & 0x80))
    296		return;
    297
    298	if (status & 0x40) {
    299		timer = opl3->timer1;
    300		snd_timer_interrupt(timer, timer->sticks);
    301	}
    302	if (status & 0x20) {
    303		timer = opl3->timer2;
    304		snd_timer_interrupt(timer, timer->sticks);
    305	}
    306}
    307
    308EXPORT_SYMBOL(snd_opl3_interrupt);
    309
    310/*
    311
    312 */
    313
    314static int snd_opl3_free(struct snd_opl3 *opl3)
    315{
    316	if (snd_BUG_ON(!opl3))
    317		return -ENXIO;
    318	if (opl3->private_free)
    319		opl3->private_free(opl3);
    320	snd_opl3_clear_patches(opl3);
    321	release_and_free_resource(opl3->res_l_port);
    322	release_and_free_resource(opl3->res_r_port);
    323	kfree(opl3);
    324	return 0;
    325}
    326
    327static int snd_opl3_dev_free(struct snd_device *device)
    328{
    329	struct snd_opl3 *opl3 = device->device_data;
    330	return snd_opl3_free(opl3);
    331}
    332
    333int snd_opl3_new(struct snd_card *card,
    334		 unsigned short hardware,
    335		 struct snd_opl3 **ropl3)
    336{
    337	static const struct snd_device_ops ops = {
    338		.dev_free = snd_opl3_dev_free,
    339	};
    340	struct snd_opl3 *opl3;
    341	int err;
    342
    343	*ropl3 = NULL;
    344	opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL);
    345	if (!opl3)
    346		return -ENOMEM;
    347
    348	opl3->card = card;
    349	opl3->hardware = hardware;
    350	spin_lock_init(&opl3->reg_lock);
    351	spin_lock_init(&opl3->timer_lock);
    352
    353	err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops);
    354	if (err < 0) {
    355		snd_opl3_free(opl3);
    356		return err;
    357	}
    358
    359	*ropl3 = opl3;
    360	return 0;
    361}
    362
    363EXPORT_SYMBOL(snd_opl3_new);
    364
    365int snd_opl3_init(struct snd_opl3 *opl3)
    366{
    367	if (! opl3->command) {
    368		printk(KERN_ERR "snd_opl3_init: command not defined!\n");
    369		return -EINVAL;
    370	}
    371
    372	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
    373	/* Melodic mode */
    374	opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00);
    375
    376	switch (opl3->hardware & OPL3_HW_MASK) {
    377	case OPL3_HW_OPL2:
    378		opl3->max_voices = MAX_OPL2_VOICES;
    379		break;
    380	case OPL3_HW_OPL3:
    381	case OPL3_HW_OPL4:
    382		opl3->max_voices = MAX_OPL3_VOICES;
    383		/* Enter OPL3 mode */
    384		opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE);
    385	}
    386	return 0;
    387}
    388
    389EXPORT_SYMBOL(snd_opl3_init);
    390
    391int snd_opl3_create(struct snd_card *card,
    392		    unsigned long l_port,
    393		    unsigned long r_port,
    394		    unsigned short hardware,
    395		    int integrated,
    396		    struct snd_opl3 ** ropl3)
    397{
    398	struct snd_opl3 *opl3;
    399	int err;
    400
    401	*ropl3 = NULL;
    402	err = snd_opl3_new(card, hardware, &opl3);
    403	if (err < 0)
    404		return err;
    405	if (! integrated) {
    406		opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)");
    407		if (!opl3->res_l_port) {
    408			snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port);
    409			snd_device_free(card, opl3);
    410			return -EBUSY;
    411		}
    412		if (r_port != 0) {
    413			opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)");
    414			if (!opl3->res_r_port) {
    415				snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
    416				snd_device_free(card, opl3);
    417				return -EBUSY;
    418			}
    419		}
    420	}
    421	opl3->l_port = l_port;
    422	opl3->r_port = r_port;
    423
    424	switch (opl3->hardware) {
    425	/* some hardware doesn't support timers */
    426	case OPL3_HW_OPL3_SV:
    427	case OPL3_HW_OPL3_CS:
    428	case OPL3_HW_OPL3_FM801:
    429		opl3->command = &snd_opl3_command;
    430		break;
    431	default:
    432		opl3->command = &snd_opl2_command;
    433		err = snd_opl3_detect(opl3);
    434		if (err < 0) {
    435			snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n",
    436				   opl3->l_port, opl3->r_port);
    437			snd_device_free(card, opl3);
    438			return err;
    439		}
    440		/* detect routine returns correct hardware type */
    441		switch (opl3->hardware & OPL3_HW_MASK) {
    442		case OPL3_HW_OPL3:
    443		case OPL3_HW_OPL4:
    444			opl3->command = &snd_opl3_command;
    445		}
    446	}
    447
    448	snd_opl3_init(opl3);
    449
    450	*ropl3 = opl3;
    451	return 0;
    452}
    453
    454EXPORT_SYMBOL(snd_opl3_create);
    455
    456int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
    457{
    458	int err;
    459
    460	if (timer1_dev >= 0) {
    461		err = snd_opl3_timer1_init(opl3, timer1_dev);
    462		if (err < 0)
    463			return err;
    464	}
    465	if (timer2_dev >= 0) {
    466		err = snd_opl3_timer2_init(opl3, timer2_dev);
    467		if (err < 0) {
    468			snd_device_free(opl3->card, opl3->timer1);
    469			opl3->timer1 = NULL;
    470			return err;
    471		}
    472	}
    473	return 0;
    474}
    475
    476EXPORT_SYMBOL(snd_opl3_timer_new);
    477
    478int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
    479		       int device, int seq_device,
    480		       struct snd_hwdep ** rhwdep)
    481{
    482	struct snd_hwdep *hw;
    483	struct snd_card *card = opl3->card;
    484	int err;
    485
    486	if (rhwdep)
    487		*rhwdep = NULL;
    488
    489	/* create hardware dependent device (direct FM) */
    490
    491	err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw);
    492	if (err < 0) {
    493		snd_device_free(card, opl3);
    494		return err;
    495	}
    496	hw->private_data = opl3;
    497	hw->exclusive = 1;
    498#ifdef CONFIG_SND_OSSEMUL
    499	if (device == 0)
    500		hw->oss_type = SNDRV_OSS_DEVICE_TYPE_DMFM;
    501#endif
    502	strcpy(hw->name, hw->id);
    503	switch (opl3->hardware & OPL3_HW_MASK) {
    504	case OPL3_HW_OPL2:
    505		strcpy(hw->name, "OPL2 FM");
    506		hw->iface = SNDRV_HWDEP_IFACE_OPL2;
    507		break;
    508	case OPL3_HW_OPL3:
    509		strcpy(hw->name, "OPL3 FM");
    510		hw->iface = SNDRV_HWDEP_IFACE_OPL3;
    511		break;
    512	case OPL3_HW_OPL4:
    513		strcpy(hw->name, "OPL4 FM");
    514		hw->iface = SNDRV_HWDEP_IFACE_OPL4;
    515		break;
    516	}
    517
    518	/* operators - only ioctl */
    519	hw->ops.open = snd_opl3_open;
    520	hw->ops.ioctl = snd_opl3_ioctl;
    521	hw->ops.write = snd_opl3_write;
    522	hw->ops.release = snd_opl3_release;
    523
    524	opl3->hwdep = hw;
    525	opl3->seq_dev_num = seq_device;
    526#if IS_ENABLED(CONFIG_SND_SEQUENCER)
    527	if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,
    528			       sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) {
    529		strcpy(opl3->seq_dev->name, hw->name);
    530		*(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3;
    531	}
    532#endif
    533	if (rhwdep)
    534		*rhwdep = hw;
    535	return 0;
    536}
    537
    538EXPORT_SYMBOL(snd_opl3_hwdep_new);