18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 48c2ecf20Sopenharmony_ci * I/O routines for GF1/InterWave synthesizer chips 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/delay.h> 88c2ecf20Sopenharmony_ci#include <linux/time.h> 98c2ecf20Sopenharmony_ci#include <sound/core.h> 108c2ecf20Sopenharmony_ci#include <sound/gus.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_civoid snd_gf1_delay(struct snd_gus_card * gus) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci int i; 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 178c2ecf20Sopenharmony_ci mb(); 188c2ecf20Sopenharmony_ci inb(GUSP(gus, DRAM)); 198c2ecf20Sopenharmony_ci } 208c2ecf20Sopenharmony_ci} 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* 238c2ecf20Sopenharmony_ci * ======================================================================= 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* 278c2ecf20Sopenharmony_ci * ok.. stop of control registers (wave & ramp) need some special things.. 288c2ecf20Sopenharmony_ci * big UltraClick (tm) elimination... 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic inline void __snd_gf1_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci unsigned char value; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci outb(reg | 0x80, gus->gf1.reg_regsel); 368c2ecf20Sopenharmony_ci mb(); 378c2ecf20Sopenharmony_ci value = inb(gus->gf1.reg_data8); 388c2ecf20Sopenharmony_ci mb(); 398c2ecf20Sopenharmony_ci outb(reg, gus->gf1.reg_regsel); 408c2ecf20Sopenharmony_ci mb(); 418c2ecf20Sopenharmony_ci outb((value | 0x03) & ~(0x80 | 0x20), gus->gf1.reg_data8); 428c2ecf20Sopenharmony_ci mb(); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic inline void __snd_gf1_write8(struct snd_gus_card * gus, 468c2ecf20Sopenharmony_ci unsigned char reg, 478c2ecf20Sopenharmony_ci unsigned char data) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci outb(reg, gus->gf1.reg_regsel); 508c2ecf20Sopenharmony_ci mb(); 518c2ecf20Sopenharmony_ci outb(data, gus->gf1.reg_data8); 528c2ecf20Sopenharmony_ci mb(); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic inline unsigned char __snd_gf1_look8(struct snd_gus_card * gus, 568c2ecf20Sopenharmony_ci unsigned char reg) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci outb(reg, gus->gf1.reg_regsel); 598c2ecf20Sopenharmony_ci mb(); 608c2ecf20Sopenharmony_ci return inb(gus->gf1.reg_data8); 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic inline void __snd_gf1_write16(struct snd_gus_card * gus, 648c2ecf20Sopenharmony_ci unsigned char reg, unsigned int data) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci outb(reg, gus->gf1.reg_regsel); 678c2ecf20Sopenharmony_ci mb(); 688c2ecf20Sopenharmony_ci outw((unsigned short) data, gus->gf1.reg_data16); 698c2ecf20Sopenharmony_ci mb(); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic inline unsigned short __snd_gf1_look16(struct snd_gus_card * gus, 738c2ecf20Sopenharmony_ci unsigned char reg) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci outb(reg, gus->gf1.reg_regsel); 768c2ecf20Sopenharmony_ci mb(); 778c2ecf20Sopenharmony_ci return inw(gus->gf1.reg_data16); 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic inline void __snd_gf1_adlib_write(struct snd_gus_card * gus, 818c2ecf20Sopenharmony_ci unsigned char reg, unsigned char data) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci outb(reg, gus->gf1.reg_timerctrl); 848c2ecf20Sopenharmony_ci inb(gus->gf1.reg_timerctrl); 858c2ecf20Sopenharmony_ci inb(gus->gf1.reg_timerctrl); 868c2ecf20Sopenharmony_ci outb(data, gus->gf1.reg_timerdata); 878c2ecf20Sopenharmony_ci inb(gus->gf1.reg_timerctrl); 888c2ecf20Sopenharmony_ci inb(gus->gf1.reg_timerctrl); 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic inline void __snd_gf1_write_addr(struct snd_gus_card * gus, unsigned char reg, 928c2ecf20Sopenharmony_ci unsigned int addr, int w_16bit) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci if (gus->gf1.enh_mode) { 958c2ecf20Sopenharmony_ci if (w_16bit) 968c2ecf20Sopenharmony_ci addr = ((addr >> 1) & ~0x0000000f) | (addr & 0x0000000f); 978c2ecf20Sopenharmony_ci __snd_gf1_write8(gus, SNDRV_GF1_VB_UPPER_ADDRESS, (unsigned char) ((addr >> 26) & 0x03)); 988c2ecf20Sopenharmony_ci } else if (w_16bit) 998c2ecf20Sopenharmony_ci addr = (addr & 0x00c0000f) | ((addr & 0x003ffff0) >> 1); 1008c2ecf20Sopenharmony_ci __snd_gf1_write16(gus, reg, (unsigned short) (addr >> 11)); 1018c2ecf20Sopenharmony_ci __snd_gf1_write16(gus, reg + 1, (unsigned short) (addr << 5)); 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic inline unsigned int __snd_gf1_read_addr(struct snd_gus_card * gus, 1058c2ecf20Sopenharmony_ci unsigned char reg, short w_16bit) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci unsigned int res; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci res = ((unsigned int) __snd_gf1_look16(gus, reg | 0x80) << 11) & 0xfff800; 1108c2ecf20Sopenharmony_ci res |= ((unsigned int) __snd_gf1_look16(gus, (reg + 1) | 0x80) >> 5) & 0x0007ff; 1118c2ecf20Sopenharmony_ci if (gus->gf1.enh_mode) { 1128c2ecf20Sopenharmony_ci res |= (unsigned int) __snd_gf1_look8(gus, SNDRV_GF1_VB_UPPER_ADDRESS | 0x80) << 26; 1138c2ecf20Sopenharmony_ci if (w_16bit) 1148c2ecf20Sopenharmony_ci res = ((res << 1) & 0xffffffe0) | (res & 0x0000000f); 1158c2ecf20Sopenharmony_ci } else if (w_16bit) 1168c2ecf20Sopenharmony_ci res = ((res & 0x001ffff0) << 1) | (res & 0x00c0000f); 1178c2ecf20Sopenharmony_ci return res; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* 1228c2ecf20Sopenharmony_ci * ======================================================================= 1238c2ecf20Sopenharmony_ci */ 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_civoid snd_gf1_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci __snd_gf1_ctrl_stop(gus, reg); 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_civoid snd_gf1_write8(struct snd_gus_card * gus, 1318c2ecf20Sopenharmony_ci unsigned char reg, 1328c2ecf20Sopenharmony_ci unsigned char data) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci __snd_gf1_write8(gus, reg, data); 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ciunsigned char snd_gf1_look8(struct snd_gus_card * gus, unsigned char reg) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci return __snd_gf1_look8(gus, reg); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_civoid snd_gf1_write16(struct snd_gus_card * gus, 1438c2ecf20Sopenharmony_ci unsigned char reg, 1448c2ecf20Sopenharmony_ci unsigned int data) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci __snd_gf1_write16(gus, reg, data); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ciunsigned short snd_gf1_look16(struct snd_gus_card * gus, unsigned char reg) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci return __snd_gf1_look16(gus, reg); 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_civoid snd_gf1_adlib_write(struct snd_gus_card * gus, 1558c2ecf20Sopenharmony_ci unsigned char reg, 1568c2ecf20Sopenharmony_ci unsigned char data) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci __snd_gf1_adlib_write(gus, reg, data); 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_civoid snd_gf1_write_addr(struct snd_gus_card * gus, unsigned char reg, 1628c2ecf20Sopenharmony_ci unsigned int addr, short w_16bit) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci __snd_gf1_write_addr(gus, reg, addr, w_16bit); 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ciunsigned int snd_gf1_read_addr(struct snd_gus_card * gus, 1688c2ecf20Sopenharmony_ci unsigned char reg, 1698c2ecf20Sopenharmony_ci short w_16bit) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci return __snd_gf1_read_addr(gus, reg, w_16bit); 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci/* 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_civoid snd_gf1_i_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci unsigned long flags; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 1838c2ecf20Sopenharmony_ci __snd_gf1_ctrl_stop(gus, reg); 1848c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_civoid snd_gf1_i_write8(struct snd_gus_card * gus, 1888c2ecf20Sopenharmony_ci unsigned char reg, 1898c2ecf20Sopenharmony_ci unsigned char data) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci unsigned long flags; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 1948c2ecf20Sopenharmony_ci __snd_gf1_write8(gus, reg, data); 1958c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ciunsigned char snd_gf1_i_look8(struct snd_gus_card * gus, unsigned char reg) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci unsigned long flags; 2018c2ecf20Sopenharmony_ci unsigned char res; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 2048c2ecf20Sopenharmony_ci res = __snd_gf1_look8(gus, reg); 2058c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 2068c2ecf20Sopenharmony_ci return res; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_civoid snd_gf1_i_write16(struct snd_gus_card * gus, 2108c2ecf20Sopenharmony_ci unsigned char reg, 2118c2ecf20Sopenharmony_ci unsigned int data) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci unsigned long flags; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 2168c2ecf20Sopenharmony_ci __snd_gf1_write16(gus, reg, data); 2178c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ciunsigned short snd_gf1_i_look16(struct snd_gus_card * gus, unsigned char reg) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci unsigned long flags; 2238c2ecf20Sopenharmony_ci unsigned short res; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 2268c2ecf20Sopenharmony_ci res = __snd_gf1_look16(gus, reg); 2278c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 2288c2ecf20Sopenharmony_ci return res; 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci#if 0 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_civoid snd_gf1_i_adlib_write(struct snd_gus_card * gus, 2348c2ecf20Sopenharmony_ci unsigned char reg, 2358c2ecf20Sopenharmony_ci unsigned char data) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci unsigned long flags; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 2408c2ecf20Sopenharmony_ci __snd_gf1_adlib_write(gus, reg, data); 2418c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_civoid snd_gf1_i_write_addr(struct snd_gus_card * gus, unsigned char reg, 2458c2ecf20Sopenharmony_ci unsigned int addr, short w_16bit) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci unsigned long flags; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 2508c2ecf20Sopenharmony_ci __snd_gf1_write_addr(gus, reg, addr, w_16bit); 2518c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci#endif /* 0 */ 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci#ifdef CONFIG_SND_DEBUG 2578c2ecf20Sopenharmony_cistatic unsigned int snd_gf1_i_read_addr(struct snd_gus_card * gus, 2588c2ecf20Sopenharmony_ci unsigned char reg, short w_16bit) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci unsigned int res; 2618c2ecf20Sopenharmony_ci unsigned long flags; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 2648c2ecf20Sopenharmony_ci res = __snd_gf1_read_addr(gus, reg, w_16bit); 2658c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 2668c2ecf20Sopenharmony_ci return res; 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci#endif 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci/* 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_civoid snd_gf1_dram_addr(struct snd_gus_card * gus, unsigned int addr) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci outb(0x43, gus->gf1.reg_regsel); 2778c2ecf20Sopenharmony_ci mb(); 2788c2ecf20Sopenharmony_ci outw((unsigned short) addr, gus->gf1.reg_data16); 2798c2ecf20Sopenharmony_ci mb(); 2808c2ecf20Sopenharmony_ci outb(0x44, gus->gf1.reg_regsel); 2818c2ecf20Sopenharmony_ci mb(); 2828c2ecf20Sopenharmony_ci outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); 2838c2ecf20Sopenharmony_ci mb(); 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_civoid snd_gf1_poke(struct snd_gus_card * gus, unsigned int addr, unsigned char data) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci unsigned long flags; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 2918c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); 2928c2ecf20Sopenharmony_ci mb(); 2938c2ecf20Sopenharmony_ci outw((unsigned short) addr, gus->gf1.reg_data16); 2948c2ecf20Sopenharmony_ci mb(); 2958c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); 2968c2ecf20Sopenharmony_ci mb(); 2978c2ecf20Sopenharmony_ci outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); 2988c2ecf20Sopenharmony_ci mb(); 2998c2ecf20Sopenharmony_ci outb(data, gus->gf1.reg_dram); 3008c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ciunsigned char snd_gf1_peek(struct snd_gus_card * gus, unsigned int addr) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci unsigned long flags; 3068c2ecf20Sopenharmony_ci unsigned char res; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 3098c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); 3108c2ecf20Sopenharmony_ci mb(); 3118c2ecf20Sopenharmony_ci outw((unsigned short) addr, gus->gf1.reg_data16); 3128c2ecf20Sopenharmony_ci mb(); 3138c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); 3148c2ecf20Sopenharmony_ci mb(); 3158c2ecf20Sopenharmony_ci outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); 3168c2ecf20Sopenharmony_ci mb(); 3178c2ecf20Sopenharmony_ci res = inb(gus->gf1.reg_dram); 3188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 3198c2ecf20Sopenharmony_ci return res; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci#if 0 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_civoid snd_gf1_pokew(struct snd_gus_card * gus, unsigned int addr, unsigned short data) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci unsigned long flags; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci#ifdef CONFIG_SND_DEBUG 3298c2ecf20Sopenharmony_ci if (!gus->interwave) 3308c2ecf20Sopenharmony_ci snd_printk(KERN_DEBUG "snd_gf1_pokew - GF1!!!\n"); 3318c2ecf20Sopenharmony_ci#endif 3328c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 3338c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); 3348c2ecf20Sopenharmony_ci mb(); 3358c2ecf20Sopenharmony_ci outw((unsigned short) addr, gus->gf1.reg_data16); 3368c2ecf20Sopenharmony_ci mb(); 3378c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); 3388c2ecf20Sopenharmony_ci mb(); 3398c2ecf20Sopenharmony_ci outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); 3408c2ecf20Sopenharmony_ci mb(); 3418c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); 3428c2ecf20Sopenharmony_ci mb(); 3438c2ecf20Sopenharmony_ci outw(data, gus->gf1.reg_data16); 3448c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ciunsigned short snd_gf1_peekw(struct snd_gus_card * gus, unsigned int addr) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci unsigned long flags; 3508c2ecf20Sopenharmony_ci unsigned short res; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci#ifdef CONFIG_SND_DEBUG 3538c2ecf20Sopenharmony_ci if (!gus->interwave) 3548c2ecf20Sopenharmony_ci snd_printk(KERN_DEBUG "snd_gf1_peekw - GF1!!!\n"); 3558c2ecf20Sopenharmony_ci#endif 3568c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 3578c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); 3588c2ecf20Sopenharmony_ci mb(); 3598c2ecf20Sopenharmony_ci outw((unsigned short) addr, gus->gf1.reg_data16); 3608c2ecf20Sopenharmony_ci mb(); 3618c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); 3628c2ecf20Sopenharmony_ci mb(); 3638c2ecf20Sopenharmony_ci outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); 3648c2ecf20Sopenharmony_ci mb(); 3658c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); 3668c2ecf20Sopenharmony_ci mb(); 3678c2ecf20Sopenharmony_ci res = inw(gus->gf1.reg_data16); 3688c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 3698c2ecf20Sopenharmony_ci return res; 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_civoid snd_gf1_dram_setmem(struct snd_gus_card * gus, unsigned int addr, 3738c2ecf20Sopenharmony_ci unsigned short value, unsigned int count) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci unsigned long port; 3768c2ecf20Sopenharmony_ci unsigned long flags; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci#ifdef CONFIG_SND_DEBUG 3798c2ecf20Sopenharmony_ci if (!gus->interwave) 3808c2ecf20Sopenharmony_ci snd_printk(KERN_DEBUG "snd_gf1_dram_setmem - GF1!!!\n"); 3818c2ecf20Sopenharmony_ci#endif 3828c2ecf20Sopenharmony_ci addr &= ~1; 3838c2ecf20Sopenharmony_ci count >>= 1; 3848c2ecf20Sopenharmony_ci port = GUSP(gus, GF1DATALOW); 3858c2ecf20Sopenharmony_ci spin_lock_irqsave(&gus->reg_lock, flags); 3868c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); 3878c2ecf20Sopenharmony_ci mb(); 3888c2ecf20Sopenharmony_ci outw((unsigned short) addr, gus->gf1.reg_data16); 3898c2ecf20Sopenharmony_ci mb(); 3908c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); 3918c2ecf20Sopenharmony_ci mb(); 3928c2ecf20Sopenharmony_ci outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); 3938c2ecf20Sopenharmony_ci mb(); 3948c2ecf20Sopenharmony_ci outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); 3958c2ecf20Sopenharmony_ci while (count--) 3968c2ecf20Sopenharmony_ci outw(value, port); 3978c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&gus->reg_lock, flags); 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci#endif /* 0 */ 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_civoid snd_gf1_select_active_voices(struct snd_gus_card * gus) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci unsigned short voices; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci static const unsigned short voices_tbl[32 - 14 + 1] = 4078c2ecf20Sopenharmony_ci { 4088c2ecf20Sopenharmony_ci 44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843, 4098c2ecf20Sopenharmony_ci 25725, 24696, 23746, 22866, 22050, 21289, 20580, 19916, 19293 4108c2ecf20Sopenharmony_ci }; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci voices = gus->gf1.active_voices; 4138c2ecf20Sopenharmony_ci if (voices > 32) 4148c2ecf20Sopenharmony_ci voices = 32; 4158c2ecf20Sopenharmony_ci if (voices < 14) 4168c2ecf20Sopenharmony_ci voices = 14; 4178c2ecf20Sopenharmony_ci if (gus->gf1.enh_mode) 4188c2ecf20Sopenharmony_ci voices = 32; 4198c2ecf20Sopenharmony_ci gus->gf1.active_voices = voices; 4208c2ecf20Sopenharmony_ci gus->gf1.playback_freq = 4218c2ecf20Sopenharmony_ci gus->gf1.enh_mode ? 44100 : voices_tbl[voices - 14]; 4228c2ecf20Sopenharmony_ci if (!gus->gf1.enh_mode) { 4238c2ecf20Sopenharmony_ci snd_gf1_i_write8(gus, SNDRV_GF1_GB_ACTIVE_VOICES, 0xc0 | (voices - 1)); 4248c2ecf20Sopenharmony_ci udelay(100); 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci#ifdef CONFIG_SND_DEBUG 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_civoid snd_gf1_print_voice_registers(struct snd_gus_card * gus) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci unsigned char mode; 4338c2ecf20Sopenharmony_ci int voice, ctrl; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci voice = gus->gf1.active_voice; 4368c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GF1 voice ctrl, ramp ctrl = 0x%x, 0x%x\n", voice, ctrl = snd_gf1_i_read8(gus, 0), snd_gf1_i_read8(gus, 0x0d)); 4378c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GF1 frequency = 0x%x\n", voice, snd_gf1_i_read16(gus, 1)); 4388c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GF1 loop start, end = 0x%x (0x%x), 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 2, ctrl & 4), snd_gf1_i_read_addr(gus, 2, (ctrl & 4) ^ 4), snd_gf1_i_read_addr(gus, 4, ctrl & 4), snd_gf1_i_read_addr(gus, 4, (ctrl & 4) ^ 4)); 4398c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GF1 ramp start, end, rate = 0x%x, 0x%x, 0x%x\n", voice, snd_gf1_i_read8(gus, 7), snd_gf1_i_read8(gus, 8), snd_gf1_i_read8(gus, 6)); 4408c2ecf20Sopenharmony_ci printk(KERN_INFO" -%i- GF1 volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 9)); 4418c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GF1 position = 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 0x0a, ctrl & 4), snd_gf1_i_read_addr(gus, 0x0a, (ctrl & 4) ^ 4)); 4428c2ecf20Sopenharmony_ci if (gus->interwave && snd_gf1_i_read8(gus, 0x19) & 0x01) { /* enhanced mode */ 4438c2ecf20Sopenharmony_ci mode = snd_gf1_i_read8(gus, 0x15); 4448c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GFA1 mode = 0x%x\n", voice, mode); 4458c2ecf20Sopenharmony_ci if (mode & 0x01) { /* Effect processor */ 4468c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GFA1 effect address = 0x%x\n", voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4)); 4478c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GFA1 effect volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x16)); 4488c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GFA1 effect volume final = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x1d)); 4498c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GFA1 effect accumulator = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x14)); 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci if (mode & 0x20) { 4528c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GFA1 left offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x13), snd_gf1_i_read16(gus, 0x13) >> 4); 4538c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GFA1 left offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1c), snd_gf1_i_read16(gus, 0x1c) >> 4); 4548c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GFA1 right offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x0c), snd_gf1_i_read16(gus, 0x0c) >> 4); 4558c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GFA1 right offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1b), snd_gf1_i_read16(gus, 0x1b) >> 4); 4568c2ecf20Sopenharmony_ci } else 4578c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); 4588c2ecf20Sopenharmony_ci } else 4598c2ecf20Sopenharmony_ci printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci#if 0 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_civoid snd_gf1_print_global_registers(struct snd_gus_card * gus) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci unsigned char global_mode = 0x00; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GF1 active voices = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ACTIVE_VOICES)); 4698c2ecf20Sopenharmony_ci if (gus->interwave) { 4708c2ecf20Sopenharmony_ci global_mode = snd_gf1_i_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE); 4718c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GF1 global mode = 0x%x\n", global_mode); 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci if (global_mode & 0x02) /* LFO enabled? */ 4748c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GF1 LFO base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_LFO_BASE)); 4758c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GF1 voices IRQ read = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VOICES_IRQ_READ)); 4768c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GF1 DRAM DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL)); 4778c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GF1 DRAM DMA high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW)); 4788c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GF1 DRAM IO high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_IO_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_IO_LOW)); 4798c2ecf20Sopenharmony_ci if (!gus->interwave) 4808c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GF1 record DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL)); 4818c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GF1 DRAM IO 16 = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_DRAM_IO16)); 4828c2ecf20Sopenharmony_ci if (gus->gf1.enh_mode) { 4838c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GFA1 memory config = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG)); 4848c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GFA1 memory control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MEMORY_CONTROL)); 4858c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GFA1 FIFO record base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR)); 4868c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GFA1 FIFO playback base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR)); 4878c2ecf20Sopenharmony_ci printk(KERN_INFO " -G- GFA1 interleave control = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_INTERLEAVE)); 4888c2ecf20Sopenharmony_ci } 4898c2ecf20Sopenharmony_ci} 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_civoid snd_gf1_print_setup_registers(struct snd_gus_card * gus) 4928c2ecf20Sopenharmony_ci{ 4938c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- mix control = 0x%x\n", inb(GUSP(gus, MIXCNTRLREG))); 4948c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- IRQ status = 0x%x\n", inb(GUSP(gus, IRQSTAT))); 4958c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- timer control = 0x%x\n", inb(GUSP(gus, TIMERCNTRL))); 4968c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- timer data = 0x%x\n", inb(GUSP(gus, TIMERDATA))); 4978c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- status read = 0x%x\n", inb(GUSP(gus, REGCNTRLS))); 4988c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- Sound Blaster control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL)); 4998c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- AdLib timer 1/2 = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1), snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2)); 5008c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- reset = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)); 5018c2ecf20Sopenharmony_ci if (gus->interwave) { 5028c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- compatibility = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_COMPATIBILITY)); 5038c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- decode control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DECODE_CONTROL)); 5048c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- version number = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER)); 5058c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- MPU-401 emul. control A/B = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A), snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B)); 5068c2ecf20Sopenharmony_ci printk(KERN_INFO " -S- emulation IRQ = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_EMULATION_IRQ)); 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_civoid snd_gf1_peek_print_block(struct snd_gus_card * gus, unsigned int addr, int count, int w_16bit) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci if (!w_16bit) { 5138c2ecf20Sopenharmony_ci while (count-- > 0) 5148c2ecf20Sopenharmony_ci printk(count > 0 ? "%02x:" : "%02x", snd_gf1_peek(gus, addr++)); 5158c2ecf20Sopenharmony_ci } else { 5168c2ecf20Sopenharmony_ci while (count-- > 0) { 5178c2ecf20Sopenharmony_ci printk(count > 0 ? "%04x:" : "%04x", snd_gf1_peek(gus, addr) | (snd_gf1_peek(gus, addr + 1) << 8)); 5188c2ecf20Sopenharmony_ci addr += 2; 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci#endif /* 0 */ 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci#endif 526