⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opl3sa2.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * sound/opl3sa2.c * * A low level driver for Yamaha OPL3-SA2 and SA3 cards. * NOTE: All traces of the name OPL3-SAx have now (December 2000) been *       removed from the driver code, as an email exchange with Yamaha *       provided the information that the YMF-719 is indeed just a *       re-badged 715. * * Copyright 1998-2001 Scott Murray <scott@spiteful.org> * * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen * and others.  Now incorporates code/ideas from pss.c, also by Hannu * Savolainen.  Both of those files are distributed with the following * license: * * "Copyright (C) by Hannu Savolainen 1993-1997 * *  OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) *  Version 2 (June 1991). See the "COPYING" file distributed with this software *  for more info." * * As such, in accordance with the above license, this file, opl3sa2.c, is * distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991). * See the "COPYING" file distributed with this software for more information. * * Change History * -------------- * Scott Murray            Original driver (Jun 14, 1998) * Paul J.Y. Lahaie        Changed probing / attach code order * Scott Murray            Added mixer support (Dec 03, 1998) * Scott Murray            Changed detection code to be more forgiving, *                         added force option as last resort, *                         fixed ioctl return values. (Dec 30, 1998) * Scott Murray            Simpler detection code should work all the time now *                         (with thanks to Ben Hutchings for the heuristic), *                         removed now unnecessary force option. (Jan 5, 1999) * Christoph Hellwig	   Adapted to module_init/module_exit (Mar 4, 2000) * Scott Murray            Reworked SA2 versus SA3 mixer code, updated chipset *                         version detection code (again!). (Dec 5, 2000) * Scott Murray            Adjusted master volume mixer scaling. (Dec 6, 2000) * Scott Murray            Based on a patch by Joel Yliluoma (aka Bisqwit), *                         integrated wide mixer and adjusted mic, bass, treble *                         scaling. (Dec 6, 2000) * Scott Murray            Based on a patch by Peter Englmaier, integrated *                         ymode and loopback options. (Dec 6, 2000) * Scott Murray            Inspired by a patch by Peter Englmaier, and based on *                         what ALSA does, added initialization code for the *                         default DMA and IRQ settings. (Dec 6, 2000) * Scott Murray            Added some more checks to the card detection code, *                         based on what ALSA does. (Dec 12, 2000) * Scott Murray            Inspired by similar patches from John Fremlin, *                         Jim Radford, Mike Rolig, and Ingmar Steen, added 2.4 *                         ISA PnP API support, mainly based on bits from *                         sb_card.c and awe_wave.c. (Dec 12, 2000) * Scott Murray            Some small cleanups to the init code output. *                         (Jan 7, 2001) * Zwane Mwaikambo	   Added PM support. (Dec 4 2001) * */#include <linux/config.h>#include <linux/init.h>#include <linux/module.h>#include <linux/isapnp.h>#include <linux/pm.h>#include <linux/delay.h>#include "sound_config.h"#include "ad1848.h"#include "mpu401.h"#define OPL3SA2_MODULE_NAME	"opl3sa2"/* Useful control port indexes: */#define OPL3SA2_PM	     0x01#define OPL3SA2_SYS_CTRL     0x02#define OPL3SA2_IRQ_CONFIG   0x03#define OPL3SA2_DMA_CONFIG   0x06#define OPL3SA2_MASTER_LEFT  0x07#define OPL3SA2_MASTER_RIGHT 0x08#define OPL3SA2_MIC          0x09#define OPL3SA2_MISC         0x0A#define OPL3SA3_WIDE         0x14#define OPL3SA3_BASS         0x15#define OPL3SA3_TREBLE       0x16/* Useful constants: */#define DEFAULT_VOLUME 50#define DEFAULT_MIC    50#define DEFAULT_TIMBRE 0/* Power saving modes */#define OPL3SA2_PM_MODE1	0x05#define OPL3SA2_PM_MODE2	0x04#define OPL3SA2_PM_MODE3	0x03/* For checking against what the card returns: */#define VERSION_UNKNOWN 0#define VERSION_YMF711  1#define VERSION_YMF715  2#define VERSION_YMF715B 3#define VERSION_YMF715E 4/* also assuming that anything > 4 but <= 7 is a 715E *//* Chipset type constants for use below */#define CHIPSET_UNKNOWN -1#define CHIPSET_OPL3SA2 0#define CHIPSET_OPL3SA3 1#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE#define OPL3SA2_CARDS_MAX 4#else#define OPL3SA2_CARDS_MAX 1#endif/* This should be pretty obvious */static int opl3sa2_cards_num; /* = 0 *//* What's my version(s)? */static int chipset[OPL3SA2_CARDS_MAX] = { CHIPSET_UNKNOWN };/* Oh well, let's just cache the name(s) */static char chipset_name[OPL3SA2_CARDS_MAX][12];/* Where's my mixer(s)? */static int opl3sa2_mixer[OPL3SA2_CARDS_MAX] = { -1 };/* Bag o' mixer data */typedef struct opl3sa2_mixerdata_tag {	unsigned short cfg_port;	unsigned short padding;	unsigned char  pm_reg;	unsigned int   in_suspend;	struct pm_dev  *pmdev;	unsigned int   card;	unsigned int   volume_l;	unsigned int   volume_r;	unsigned int   mic;	unsigned int   bass_l;	unsigned int   bass_r;	unsigned int   treble_l;	unsigned int   treble_r;	unsigned int   wide_l;	unsigned int   wide_r;} opl3sa2_mixerdata;static opl3sa2_mixerdata opl3sa2_data[OPL3SA2_CARDS_MAX];static struct address_info cfg[OPL3SA2_CARDS_MAX];static struct address_info cfg_mss[OPL3SA2_CARDS_MAX];static struct address_info cfg_mpu[OPL3SA2_CARDS_MAX];/* Our parameters */static int __initdata io	= -1;static int __initdata mss_io	= -1;static int __initdata mpu_io	= -1;static int __initdata irq	= -1;static int __initdata dma	= -1;static int __initdata dma2	= -1;static int __initdata ymode	= -1;static int __initdata loopback	= -1;#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE/* PnP specific parameters */static int __initdata isapnp = 1;static int __initdata multiple = 1;/* PnP devices */struct pci_dev* opl3sa2_dev[OPL3SA2_CARDS_MAX];/* Whether said devices have been activated */static int opl3sa2_activated[OPL3SA2_CARDS_MAX];#elsestatic int __initdata isapnp; /* = 0 */static int __initdata multiple; /* = 0 */#endifMODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");MODULE_AUTHOR("Scott Murray <scott@spiteful.org>");MODULE_LICENSE("GPL");MODULE_PARM(io, "i");MODULE_PARM_DESC(io, "Set I/O base of OPL3-SA2 or SA3 card (usually 0x370.  Address must be even and must be from 0x100 to 0xFFE)");MODULE_PARM(mss_io, "i");MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)");MODULE_PARM(mpu_io, "i");MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be even and must be from 0x300 to 0x334)");MODULE_PARM(irq, "i");MODULE_PARM_DESC(mss_irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");MODULE_PARM(dma, "i");MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");MODULE_PARM(dma2, "i");MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");MODULE_PARM(ymode, "i");MODULE_PARM_DESC(ymode, "Set Yamaha 3D enhancement mode (0 = Desktop/Normal, 1 = Notebook PC (1), 2 = Notebook PC (2), 3 = Hi-Fi)");MODULE_PARM(loopback, "i");MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)");#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULEMODULE_PARM(isapnp, "i");MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled");MODULE_PARM(multiple, "i");MODULE_PARM_DESC(multiple, "When set to 0, will not search for multiple cards");#endif/* * Standard read and write functions*/static inline void opl3sa2_write(unsigned short port,				 unsigned char  index,				 unsigned char  data){	outb_p(index, port);	outb(data, port + 1);}static inline void opl3sa2_read(unsigned short port,				unsigned char  index,				unsigned char* data){	outb_p(index, port);	*data = inb(port + 1);}/* * All of the mixer functions... */static void opl3sa2_set_volume(opl3sa2_mixerdata* devc, int left, int right){	static unsigned char scale[101] = {		0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e,		0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c,		0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b,		0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09,		0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08,		0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,		0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,		0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,		0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,		0x00	};	unsigned char vol;	vol = scale[left];	/* If level is zero, turn on mute */	if(!left)		vol |= 0x80;	opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_LEFT, vol);	vol = scale[right];	/* If level is zero, turn on mute */	if(!right)		vol |= 0x80;	opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_RIGHT, vol);}static void opl3sa2_set_mic(opl3sa2_mixerdata* devc, int level){	unsigned char vol = 0x1F;	if((level >= 0) && (level <= 100))		vol = 0x1F - (unsigned char) (32 * level / 101);	/* If level is zero, turn on mute */	if(!level)		vol |= 0x80;	opl3sa2_write(devc->cfg_port, OPL3SA2_MIC, vol);}static void opl3sa3_set_bass(opl3sa2_mixerdata* devc, int left, int right){	unsigned char bass;	bass = left ? ((unsigned char) (8 * left / 101)) : 0; 	bass |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;	opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass);}static void opl3sa3_set_treble(opl3sa2_mixerdata* devc, int left, int right){		unsigned char treble;	treble = left ? ((unsigned char) (8 * left / 101)) : 0; 	treble |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;	opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble);}static void opl3sa3_set_wide(opl3sa2_mixerdata* devc, int left, int right){		unsigned char wide;	wide = left ? ((unsigned char) (8 * left / 101)) : 0; 	wide |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;	opl3sa2_write(devc->cfg_port, OPL3SA3_WIDE, wide);}static void opl3sa2_mixer_reset(opl3sa2_mixerdata* devc, int card){	if(devc) {		opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME);		devc->volume_l = devc->volume_r = DEFAULT_VOLUME;		opl3sa2_set_mic(devc, DEFAULT_MIC);		devc->mic = DEFAULT_MIC;		if(chipset[card] == CHIPSET_OPL3SA3) {			opl3sa3_set_bass(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);			devc->bass_l = devc->bass_r = DEFAULT_TIMBRE;			opl3sa3_set_treble(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);			devc->treble_l = devc->treble_r = DEFAULT_TIMBRE;		}	}}static void opl3sa2_mixer_restore(opl3sa2_mixerdata* devc, int card){	if (devc) {		opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);		opl3sa2_set_mic(devc, devc->mic);		if (chipset[card] == CHIPSET_OPL3SA3) {			opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r);			opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r);		}	}}static inline void arg_to_vol_mono(unsigned int vol, int* value){	int left;		left = vol & 0x00ff;	if (left > 100)		left = 100;	*value = left;}static inline void arg_to_vol_stereo(unsigned int vol, int* aleft, int* aright){	arg_to_vol_mono(vol, aleft);	arg_to_vol_mono(vol >> 8, aright);}static inline int ret_vol_mono(int vol){	return ((vol << 8) | vol);}static inline int ret_vol_stereo(int left, int right){	return ((right << 8) | left);}static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg){	int cmdf = cmd & 0xff;	opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc;		switch(cmdf) {		case SOUND_MIXER_VOLUME:		case SOUND_MIXER_MIC:		case SOUND_MIXER_DEVMASK:		case SOUND_MIXER_STEREODEVS: 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -