brintos

brintos / linux-shallow public Read only

0
0
Text · 41.7 KiB · 6188469 Raw
1624 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *  linux/sound/oss/dmasound/dmasound_atari.c4 *5 *  Atari TT and Falcon DMA Sound Driver6 *7 *  See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits8 *  prior to 28/01/20019 *10 *  28/01/2001 [0.1] Iain Sandoe11 *		     - added versioning12 *		     - put in and populated the hardware_afmts field.13 *             [0.2] - put in SNDCTL_DSP_GETCAPS value.14 *  01/02/2001 [0.3] - put in default hard/soft settings.15 */16 17 18#include <linux/module.h>19#include <linux/kernel.h>20#include <linux/init.h>21#include <linux/soundcard.h>22#include <linux/mm.h>23#include <linux/spinlock.h>24#include <linux/interrupt.h>25 26#include <linux/uaccess.h>27#include <asm/atariints.h>28#include <asm/atari_stram.h>29 30#include "dmasound.h"31 32#define DMASOUND_ATARI_REVISION 033#define DMASOUND_ATARI_EDITION 334 35extern void atari_microwire_cmd(int cmd);36 37static int is_falcon;38static int write_sq_ignore_int;	/* ++TeSche: used for Falcon */39 40static int expand_bal;	/* Balance factor for expanding (not volume!) */41static int expand_data;	/* Data for expanding */42 43 44/*** Translations ************************************************************/45 46 47/* ++TeSche: radically changed for new expanding purposes...48 *49 * These two routines now deal with copying/expanding/translating the samples50 * from user space into our buffer at the right frequency. They take care about51 * how much data there's actually to read, how much buffer space there is and52 * to convert samples into the right frequency/encoding. They will only work on53 * complete samples so it may happen they leave some bytes in the input stream54 * if the user didn't write a multiple of the current sample size. They both55 * return the number of bytes they've used from both streams so you may detect56 * such a situation. Luckily all programs should be able to cope with that.57 *58 * I think I've optimized anything as far as one can do in plain C, all59 * variables should fit in registers and the loops are really short. There's60 * one loop for every possible situation. Writing a more generalized and thus61 * parameterized loop would only produce slower code. Feel free to optimize62 * this in assembler if you like. :)63 *64 * I think these routines belong here because they're not yet really hardware65 * independent, especially the fact that the Falcon can play 16bit samples66 * only in stereo is hardcoded in both of them!67 *68 * ++geert: split in even more functions (one per format)69 */70 71static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,72			  u_char frame[], ssize_t *frameUsed,73			  ssize_t frameLeft);74static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,75			 u_char frame[], ssize_t *frameUsed,76			 ssize_t frameLeft);77static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,78			 u_char frame[], ssize_t *frameUsed,79			 ssize_t frameLeft);80static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,81			    u_char frame[], ssize_t *frameUsed,82			    ssize_t frameLeft);83static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,84			    u_char frame[], ssize_t *frameUsed,85			    ssize_t frameLeft);86static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,87			    u_char frame[], ssize_t *frameUsed,88			    ssize_t frameLeft);89static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,90			    u_char frame[], ssize_t *frameUsed,91			    ssize_t frameLeft);92static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,93			   u_char frame[], ssize_t *frameUsed,94			   ssize_t frameLeft);95static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,96			  u_char frame[], ssize_t *frameUsed,97			  ssize_t frameLeft);98static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,99			  u_char frame[], ssize_t *frameUsed,100			  ssize_t frameLeft);101static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,102			     u_char frame[], ssize_t *frameUsed,103			     ssize_t frameLeft);104static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,105			     u_char frame[], ssize_t *frameUsed,106			     ssize_t frameLeft);107static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,108			     u_char frame[], ssize_t *frameUsed,109			     ssize_t frameLeft);110static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,111			     u_char frame[], ssize_t *frameUsed,112			     ssize_t frameLeft);113 114 115/*** Low level stuff *********************************************************/116 117 118static void *AtaAlloc(unsigned int size, gfp_t flags);119static void AtaFree(void *, unsigned int size);120static int AtaIrqInit(void);121#ifdef MODULE122static void AtaIrqCleanUp(void);123#endif /* MODULE */124static int AtaSetBass(int bass);125static int AtaSetTreble(int treble);126static void TTSilence(void);127static void TTInit(void);128static int TTSetFormat(int format);129static int TTSetVolume(int volume);130static int TTSetGain(int gain);131static void FalconSilence(void);132static void FalconInit(void);133static int FalconSetFormat(int format);134static int FalconSetVolume(int volume);135static void AtaPlayNextFrame(int index);136static void AtaPlay(void);137static irqreturn_t AtaInterrupt(int irq, void *dummy);138 139/*** Mid level stuff *********************************************************/140 141static void TTMixerInit(void);142static void FalconMixerInit(void);143static int AtaMixerIoctl(u_int cmd, u_long arg);144static int TTMixerIoctl(u_int cmd, u_long arg);145static int FalconMixerIoctl(u_int cmd, u_long arg);146static int AtaWriteSqSetup(void);147static int AtaSqOpen(fmode_t mode);148static int TTStateInfo(char *buffer, size_t space);149static int FalconStateInfo(char *buffer, size_t space);150 151 152/*** Translations ************************************************************/153 154 155static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,156			  u_char frame[], ssize_t *frameUsed,157			  ssize_t frameLeft)158{159	char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8160							  : dmasound_alaw2dma8;161	ssize_t count, used;162	u_char *p = &frame[*frameUsed];163 164	count = min_t(unsigned long, userCount, frameLeft);165	if (dmasound.soft.stereo)166		count &= ~1;167	used = count;168	while (count > 0) {169		u_char data;170		if (get_user(data, userPtr++))171			return -EFAULT;172		*p++ = table[data];173		count--;174	}175	*frameUsed += used;176	return used;177}178 179 180static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,181			 u_char frame[], ssize_t *frameUsed,182			 ssize_t frameLeft)183{184	ssize_t count, used;185	void *p = &frame[*frameUsed];186 187	count = min_t(unsigned long, userCount, frameLeft);188	if (dmasound.soft.stereo)189		count &= ~1;190	used = count;191	if (copy_from_user(p, userPtr, count))192		return -EFAULT;193	*frameUsed += used;194	return used;195}196 197 198static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,199			 u_char frame[], ssize_t *frameUsed,200			 ssize_t frameLeft)201{202	ssize_t count, used;203 204	if (!dmasound.soft.stereo) {205		u_char *p = &frame[*frameUsed];206		count = min_t(unsigned long, userCount, frameLeft);207		used = count;208		while (count > 0) {209			u_char data;210			if (get_user(data, userPtr++))211				return -EFAULT;212			*p++ = data ^ 0x80;213			count--;214		}215	} else {216		u_short *p = (u_short *)&frame[*frameUsed];217		count = min_t(unsigned long, userCount, frameLeft)>>1;218		used = count*2;219		while (count > 0) {220			u_short data;221			if (get_user(data, (u_short __user *)userPtr))222				return -EFAULT;223			userPtr += 2;224			*p++ = data ^ 0x8080;225			count--;226		}227	}228	*frameUsed += used;229	return used;230}231 232 233static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,234			    u_char frame[], ssize_t *frameUsed,235			    ssize_t frameLeft)236{237	ssize_t count, used;238 239	if (!dmasound.soft.stereo) {240		u_short *p = (u_short *)&frame[*frameUsed];241		count = min_t(unsigned long, userCount, frameLeft)>>1;242		used = count*2;243		while (count > 0) {244			u_short data;245			if (get_user(data, (u_short __user *)userPtr))246				return -EFAULT;247			userPtr += 2;248			*p++ = data;249			*p++ = data;250			count--;251		}252		*frameUsed += used*2;253	} else {254		void *p = (u_short *)&frame[*frameUsed];255		count = min_t(unsigned long, userCount, frameLeft) & ~3;256		used = count;257		if (copy_from_user(p, userPtr, count))258			return -EFAULT;259		*frameUsed += used;260	}261	return used;262}263 264 265static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,266			    u_char frame[], ssize_t *frameUsed,267			    ssize_t frameLeft)268{269	ssize_t count, used;270 271	if (!dmasound.soft.stereo) {272		u_short *p = (u_short *)&frame[*frameUsed];273		count = min_t(unsigned long, userCount, frameLeft)>>1;274		used = count*2;275		while (count > 0) {276			u_short data;277			if (get_user(data, (u_short __user *)userPtr))278				return -EFAULT;279			userPtr += 2;280			data ^= 0x8000;281			*p++ = data;282			*p++ = data;283			count--;284		}285		*frameUsed += used*2;286	} else {287		u_long *p = (u_long *)&frame[*frameUsed];288		count = min_t(unsigned long, userCount, frameLeft)>>2;289		used = count*4;290		while (count > 0) {291			u_int data;292			if (get_user(data, (u_int __user *)userPtr))293				return -EFAULT;294			userPtr += 4;295			*p++ = data ^ 0x80008000;296			count--;297		}298		*frameUsed += used;299	}300	return used;301}302 303 304static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,305			    u_char frame[], ssize_t *frameUsed,306			    ssize_t frameLeft)307{308	ssize_t count, used;309 310	count = frameLeft;311	if (!dmasound.soft.stereo) {312		u_short *p = (u_short *)&frame[*frameUsed];313		count = min_t(unsigned long, userCount, frameLeft)>>1;314		used = count*2;315		while (count > 0) {316			u_short data;317			if (get_user(data, (u_short __user *)userPtr))318				return -EFAULT;319			userPtr += 2;320			data = le2be16(data);321			*p++ = data;322			*p++ = data;323			count--;324		}325		*frameUsed += used*2;326	} else {327		u_long *p = (u_long *)&frame[*frameUsed];328		count = min_t(unsigned long, userCount, frameLeft)>>2;329		used = count*4;330		while (count > 0) {331			u_long data;332			if (get_user(data, (u_int __user *)userPtr))333				return -EFAULT;334			userPtr += 4;335			data = le2be16dbl(data);336			*p++ = data;337			count--;338		}339		*frameUsed += used;340	}341	return used;342}343 344 345static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,346			    u_char frame[], ssize_t *frameUsed,347			    ssize_t frameLeft)348{349	ssize_t count, used;350 351	count = frameLeft;352	if (!dmasound.soft.stereo) {353		u_short *p = (u_short *)&frame[*frameUsed];354		count = min_t(unsigned long, userCount, frameLeft)>>1;355		used = count*2;356		while (count > 0) {357			u_short data;358			if (get_user(data, (u_short __user *)userPtr))359				return -EFAULT;360			userPtr += 2;361			data = le2be16(data) ^ 0x8000;362			*p++ = data;363			*p++ = data;364		}365		*frameUsed += used*2;366	} else {367		u_long *p = (u_long *)&frame[*frameUsed];368		count = min_t(unsigned long, userCount, frameLeft)>>2;369		used = count;370		while (count > 0) {371			u_long data;372			if (get_user(data, (u_int __user *)userPtr))373				return -EFAULT;374			userPtr += 4;375			data = le2be16dbl(data) ^ 0x80008000;376			*p++ = data;377			count--;378		}379		*frameUsed += used;380	}381	return used;382}383 384 385static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,386			   u_char frame[], ssize_t *frameUsed,387			   ssize_t frameLeft)388{389	char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8390							  : dmasound_alaw2dma8;391	/* this should help gcc to stuff everything into registers */392	long bal = expand_bal;393	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;394	ssize_t used, usedf;395 396	used = userCount;397	usedf = frameLeft;398	if (!dmasound.soft.stereo) {399		u_char *p = &frame[*frameUsed];400		u_char data = expand_data;401		while (frameLeft) {402			u_char c;403			if (bal < 0) {404				if (!userCount)405					break;406				if (get_user(c, userPtr++))407					return -EFAULT;408				data = table[c];409				userCount--;410				bal += hSpeed;411			}412			*p++ = data;413			frameLeft--;414			bal -= sSpeed;415		}416		expand_data = data;417	} else {418		u_short *p = (u_short *)&frame[*frameUsed];419		u_short data = expand_data;420		while (frameLeft >= 2) {421			u_char c;422			if (bal < 0) {423				if (userCount < 2)424					break;425				if (get_user(c, userPtr++))426					return -EFAULT;427				data = table[c] << 8;428				if (get_user(c, userPtr++))429					return -EFAULT;430				data |= table[c];431				userCount -= 2;432				bal += hSpeed;433			}434			*p++ = data;435			frameLeft -= 2;436			bal -= sSpeed;437		}438		expand_data = data;439	}440	expand_bal = bal;441	used -= userCount;442	*frameUsed += usedf-frameLeft;443	return used;444}445 446 447static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,448			  u_char frame[], ssize_t *frameUsed,449			  ssize_t frameLeft)450{451	/* this should help gcc to stuff everything into registers */452	long bal = expand_bal;453	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;454	ssize_t used, usedf;455 456	used = userCount;457	usedf = frameLeft;458	if (!dmasound.soft.stereo) {459		u_char *p = &frame[*frameUsed];460		u_char data = expand_data;461		while (frameLeft) {462			if (bal < 0) {463				if (!userCount)464					break;465				if (get_user(data, userPtr++))466					return -EFAULT;467				userCount--;468				bal += hSpeed;469			}470			*p++ = data;471			frameLeft--;472			bal -= sSpeed;473		}474		expand_data = data;475	} else {476		u_short *p = (u_short *)&frame[*frameUsed];477		u_short data = expand_data;478		while (frameLeft >= 2) {479			if (bal < 0) {480				if (userCount < 2)481					break;482				if (get_user(data, (u_short __user *)userPtr))483					return -EFAULT;484				userPtr += 2;485				userCount -= 2;486				bal += hSpeed;487			}488			*p++ = data;489			frameLeft -= 2;490			bal -= sSpeed;491		}492		expand_data = data;493	}494	expand_bal = bal;495	used -= userCount;496	*frameUsed += usedf-frameLeft;497	return used;498}499 500 501static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,502			  u_char frame[], ssize_t *frameUsed,503			  ssize_t frameLeft)504{505	/* this should help gcc to stuff everything into registers */506	long bal = expand_bal;507	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;508	ssize_t used, usedf;509 510	used = userCount;511	usedf = frameLeft;512	if (!dmasound.soft.stereo) {513		u_char *p = &frame[*frameUsed];514		u_char data = expand_data;515		while (frameLeft) {516			if (bal < 0) {517				if (!userCount)518					break;519				if (get_user(data, userPtr++))520					return -EFAULT;521				data ^= 0x80;522				userCount--;523				bal += hSpeed;524			}525			*p++ = data;526			frameLeft--;527			bal -= sSpeed;528		}529		expand_data = data;530	} else {531		u_short *p = (u_short *)&frame[*frameUsed];532		u_short data = expand_data;533		while (frameLeft >= 2) {534			if (bal < 0) {535				if (userCount < 2)536					break;537				if (get_user(data, (u_short __user *)userPtr))538					return -EFAULT;539				userPtr += 2;540				data ^= 0x8080;541				userCount -= 2;542				bal += hSpeed;543			}544			*p++ = data;545			frameLeft -= 2;546			bal -= sSpeed;547		}548		expand_data = data;549	}550	expand_bal = bal;551	used -= userCount;552	*frameUsed += usedf-frameLeft;553	return used;554}555 556 557static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,558			     u_char frame[], ssize_t *frameUsed,559			     ssize_t frameLeft)560{561	/* this should help gcc to stuff everything into registers */562	long bal = expand_bal;563	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;564	ssize_t used, usedf;565 566	used = userCount;567	usedf = frameLeft;568	if (!dmasound.soft.stereo) {569		u_short *p = (u_short *)&frame[*frameUsed];570		u_short data = expand_data;571		while (frameLeft >= 4) {572			if (bal < 0) {573				if (userCount < 2)574					break;575				if (get_user(data, (u_short __user *)userPtr))576					return -EFAULT;577				userPtr += 2;578				userCount -= 2;579				bal += hSpeed;580			}581			*p++ = data;582			*p++ = data;583			frameLeft -= 4;584			bal -= sSpeed;585		}586		expand_data = data;587	} else {588		u_long *p = (u_long *)&frame[*frameUsed];589		u_long data = expand_data;590		while (frameLeft >= 4) {591			if (bal < 0) {592				if (userCount < 4)593					break;594				if (get_user(data, (u_int __user *)userPtr))595					return -EFAULT;596				userPtr += 4;597				userCount -= 4;598				bal += hSpeed;599			}600			*p++ = data;601			frameLeft -= 4;602			bal -= sSpeed;603		}604		expand_data = data;605	}606	expand_bal = bal;607	used -= userCount;608	*frameUsed += usedf-frameLeft;609	return used;610}611 612 613static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,614			     u_char frame[], ssize_t *frameUsed,615			     ssize_t frameLeft)616{617	/* this should help gcc to stuff everything into registers */618	long bal = expand_bal;619	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;620	ssize_t used, usedf;621 622	used = userCount;623	usedf = frameLeft;624	if (!dmasound.soft.stereo) {625		u_short *p = (u_short *)&frame[*frameUsed];626		u_short data = expand_data;627		while (frameLeft >= 4) {628			if (bal < 0) {629				if (userCount < 2)630					break;631				if (get_user(data, (u_short __user *)userPtr))632					return -EFAULT;633				userPtr += 2;634				data ^= 0x8000;635				userCount -= 2;636				bal += hSpeed;637			}638			*p++ = data;639			*p++ = data;640			frameLeft -= 4;641			bal -= sSpeed;642		}643		expand_data = data;644	} else {645		u_long *p = (u_long *)&frame[*frameUsed];646		u_long data = expand_data;647		while (frameLeft >= 4) {648			if (bal < 0) {649				if (userCount < 4)650					break;651				if (get_user(data, (u_int __user *)userPtr))652					return -EFAULT;653				userPtr += 4;654				data ^= 0x80008000;655				userCount -= 4;656				bal += hSpeed;657			}658			*p++ = data;659			frameLeft -= 4;660			bal -= sSpeed;661		}662		expand_data = data;663	}664	expand_bal = bal;665	used -= userCount;666	*frameUsed += usedf-frameLeft;667	return used;668}669 670 671static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,672			     u_char frame[], ssize_t *frameUsed,673			     ssize_t frameLeft)674{675	/* this should help gcc to stuff everything into registers */676	long bal = expand_bal;677	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;678	ssize_t used, usedf;679 680	used = userCount;681	usedf = frameLeft;682	if (!dmasound.soft.stereo) {683		u_short *p = (u_short *)&frame[*frameUsed];684		u_short data = expand_data;685		while (frameLeft >= 4) {686			if (bal < 0) {687				if (userCount < 2)688					break;689				if (get_user(data, (u_short __user *)userPtr))690					return -EFAULT;691				userPtr += 2;692				data = le2be16(data);693				userCount -= 2;694				bal += hSpeed;695			}696			*p++ = data;697			*p++ = data;698			frameLeft -= 4;699			bal -= sSpeed;700		}701		expand_data = data;702	} else {703		u_long *p = (u_long *)&frame[*frameUsed];704		u_long data = expand_data;705		while (frameLeft >= 4) {706			if (bal < 0) {707				if (userCount < 4)708					break;709				if (get_user(data, (u_int __user *)userPtr))710					return -EFAULT;711				userPtr += 4;712				data = le2be16dbl(data);713				userCount -= 4;714				bal += hSpeed;715			}716			*p++ = data;717			frameLeft -= 4;718			bal -= sSpeed;719		}720		expand_data = data;721	}722	expand_bal = bal;723	used -= userCount;724	*frameUsed += usedf-frameLeft;725	return used;726}727 728 729static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,730			     u_char frame[], ssize_t *frameUsed,731			     ssize_t frameLeft)732{733	/* this should help gcc to stuff everything into registers */734	long bal = expand_bal;735	long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;736	ssize_t used, usedf;737 738	used = userCount;739	usedf = frameLeft;740	if (!dmasound.soft.stereo) {741		u_short *p = (u_short *)&frame[*frameUsed];742		u_short data = expand_data;743		while (frameLeft >= 4) {744			if (bal < 0) {745				if (userCount < 2)746					break;747				if (get_user(data, (u_short __user *)userPtr))748					return -EFAULT;749				userPtr += 2;750				data = le2be16(data) ^ 0x8000;751				userCount -= 2;752				bal += hSpeed;753			}754			*p++ = data;755			*p++ = data;756			frameLeft -= 4;757			bal -= sSpeed;758		}759		expand_data = data;760	} else {761		u_long *p = (u_long *)&frame[*frameUsed];762		u_long data = expand_data;763		while (frameLeft >= 4) {764			if (bal < 0) {765				if (userCount < 4)766					break;767				if (get_user(data, (u_int __user *)userPtr))768					return -EFAULT;769				userPtr += 4;770				data = le2be16dbl(data) ^ 0x80008000;771				userCount -= 4;772				bal += hSpeed;773			}774			*p++ = data;775			frameLeft -= 4;776			bal -= sSpeed;777		}778		expand_data = data;779	}780	expand_bal = bal;781	used -= userCount;782	*frameUsed += usedf-frameLeft;783	return used;784}785 786 787static TRANS transTTNormal = {788	.ct_ulaw	= ata_ct_law,789	.ct_alaw	= ata_ct_law,790	.ct_s8		= ata_ct_s8,791	.ct_u8		= ata_ct_u8,792};793 794static TRANS transTTExpanding = {795	.ct_ulaw	= ata_ctx_law,796	.ct_alaw	= ata_ctx_law,797	.ct_s8		= ata_ctx_s8,798	.ct_u8		= ata_ctx_u8,799};800 801static TRANS transFalconNormal = {802	.ct_ulaw	= ata_ct_law,803	.ct_alaw	= ata_ct_law,804	.ct_s8		= ata_ct_s8,805	.ct_u8		= ata_ct_u8,806	.ct_s16be	= ata_ct_s16be,807	.ct_u16be	= ata_ct_u16be,808	.ct_s16le	= ata_ct_s16le,809	.ct_u16le	= ata_ct_u16le810};811 812static TRANS transFalconExpanding = {813	.ct_ulaw	= ata_ctx_law,814	.ct_alaw	= ata_ctx_law,815	.ct_s8		= ata_ctx_s8,816	.ct_u8		= ata_ctx_u8,817	.ct_s16be	= ata_ctx_s16be,818	.ct_u16be	= ata_ctx_u16be,819	.ct_s16le	= ata_ctx_s16le,820	.ct_u16le	= ata_ctx_u16le,821};822 823 824/*** Low level stuff *********************************************************/825 826 827 828/*829 * Atari (TT/Falcon)830 */831 832static void *AtaAlloc(unsigned int size, gfp_t flags)833{834	return atari_stram_alloc(size, "dmasound");835}836 837static void AtaFree(void *obj, unsigned int size)838{839	atari_stram_free( obj );840}841 842static int __init AtaIrqInit(void)843{844	/* Set up timer A. Timer A845	   will receive a signal upon end of playing from the sound846	   hardware. Furthermore Timer A is able to count events847	   and will cause an interrupt after a programmed number848	   of events. So all we need to keep the music playing is849	   to provide the sound hardware with new data upon850	   an interrupt from timer A. */851	st_mfp.tim_ct_a = 0;	/* ++roman: Stop timer before programming! */852	st_mfp.tim_dt_a = 1;	/* Cause interrupt after first event. */853	st_mfp.tim_ct_a = 8;	/* Turn on event counting. */854	/* Register interrupt handler. */855	if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, 0, "DMA sound",856			AtaInterrupt))857		return 0;858	st_mfp.int_en_a |= 0x20;	/* Turn interrupt on. */859	st_mfp.int_mk_a |= 0x20;860	return 1;861}862 863#ifdef MODULE864static void AtaIrqCleanUp(void)865{866	st_mfp.tim_ct_a = 0;		/* stop timer */867	st_mfp.int_en_a &= ~0x20;	/* turn interrupt off */868	free_irq(IRQ_MFP_TIMA, AtaInterrupt);869}870#endif /* MODULE */871 872 873#define TONE_VOXWARE_TO_DB(v) \874	(((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25)875#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50)876 877 878static int AtaSetBass(int bass)879{880	dmasound.bass = TONE_VOXWARE_TO_DB(bass);881	atari_microwire_cmd(MW_LM1992_BASS(dmasound.bass));882	return TONE_DB_TO_VOXWARE(dmasound.bass);883}884 885 886static int AtaSetTreble(int treble)887{888	dmasound.treble = TONE_VOXWARE_TO_DB(treble);889	atari_microwire_cmd(MW_LM1992_TREBLE(dmasound.treble));890	return TONE_DB_TO_VOXWARE(dmasound.treble);891}892 893 894 895/*896 * TT897 */898 899 900static void TTSilence(void)901{902	tt_dmasnd.ctrl = DMASND_CTRL_OFF;903	atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */904}905 906 907static void TTInit(void)908{909	int mode, i, idx;910	const int freq[4] = {50066, 25033, 12517, 6258};911 912	/* search a frequency that fits into the allowed error range */913 914	idx = -1;915	for (i = 0; i < ARRAY_SIZE(freq); i++)916		/* this isn't as much useful for a TT than for a Falcon, but917		 * then it doesn't hurt very much to implement it for a TT too.918		 */919		if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius)920			idx = i;921	if (idx > -1) {922		dmasound.soft.speed = freq[idx];923		dmasound.trans_write = &transTTNormal;924	} else925		dmasound.trans_write = &transTTExpanding;926 927	TTSilence();928	dmasound.hard = dmasound.soft;929 930	if (dmasound.hard.speed > 50066) {931		/* we would need to squeeze the sound, but we won't do that */932		dmasound.hard.speed = 50066;933		mode = DMASND_MODE_50KHZ;934		dmasound.trans_write = &transTTNormal;935	} else if (dmasound.hard.speed > 25033) {936		dmasound.hard.speed = 50066;937		mode = DMASND_MODE_50KHZ;938	} else if (dmasound.hard.speed > 12517) {939		dmasound.hard.speed = 25033;940		mode = DMASND_MODE_25KHZ;941	} else if (dmasound.hard.speed > 6258) {942		dmasound.hard.speed = 12517;943		mode = DMASND_MODE_12KHZ;944	} else {945		dmasound.hard.speed = 6258;946		mode = DMASND_MODE_6KHZ;947	}948 949	tt_dmasnd.mode = (dmasound.hard.stereo ?950			  DMASND_MODE_STEREO : DMASND_MODE_MONO) |951		DMASND_MODE_8BIT | mode;952 953	expand_bal = -dmasound.soft.speed;954}955 956 957static int TTSetFormat(int format)958{959	/* TT sound DMA supports only 8bit modes */960 961	switch (format) {962	case AFMT_QUERY:963		return dmasound.soft.format;964	case AFMT_MU_LAW:965	case AFMT_A_LAW:966	case AFMT_S8:967	case AFMT_U8:968		break;969	default:970		format = AFMT_S8;971	}972 973	dmasound.soft.format = format;974	dmasound.soft.size = 8;975	if (dmasound.minDev == SND_DEV_DSP) {976		dmasound.dsp.format = format;977		dmasound.dsp.size = 8;978	}979	TTInit();980 981	return format;982}983 984 985#define VOLUME_VOXWARE_TO_DB(v) \986	(((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40)987#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2)988 989 990static int TTSetVolume(int volume)991{992	dmasound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff);993	atari_microwire_cmd(MW_LM1992_BALLEFT(dmasound.volume_left));994	dmasound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8);995	atari_microwire_cmd(MW_LM1992_BALRIGHT(dmasound.volume_right));996	return VOLUME_DB_TO_VOXWARE(dmasound.volume_left) |997	       (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8);998}999 1000 1001#define GAIN_VOXWARE_TO_DB(v) \1002	(((v) < 0) ? -80 : ((v) > 100) ? 0 : ((v) * 4) / 5 - 80)1003#define GAIN_DB_TO_VOXWARE(v) ((((v) + 80) * 5 + 1) / 4)1004 1005static int TTSetGain(int gain)1006{1007	dmasound.gain = GAIN_VOXWARE_TO_DB(gain);1008	atari_microwire_cmd(MW_LM1992_VOLUME(dmasound.gain));1009	return GAIN_DB_TO_VOXWARE(dmasound.gain);1010}1011 1012 1013 1014/*1015 * Falcon1016 */1017 1018 1019static void FalconSilence(void)1020{1021	/* stop playback, set sample rate 50kHz for PSG sound */1022	tt_dmasnd.ctrl = DMASND_CTRL_OFF;1023	tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT;1024	tt_dmasnd.int_div = 0; /* STE compatible divider */1025	tt_dmasnd.int_ctrl = 0x0;1026	tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */1027	tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */1028	tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */1029	tt_dmasnd.adc_src = 3; /* ADC Input = PSG */1030}1031 1032 1033static void FalconInit(void)1034{1035	int divider, i, idx;1036	const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};1037 1038	/* search a frequency that fits into the allowed error range */1039 1040	idx = -1;1041	for (i = 0; i < ARRAY_SIZE(freq); i++)1042		/* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would1043		 * be playable without expanding, but that now a kernel runtime1044		 * option1045		 */1046		if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius)1047			idx = i;1048	if (idx > -1) {1049		dmasound.soft.speed = freq[idx];1050		dmasound.trans_write = &transFalconNormal;1051	} else1052		dmasound.trans_write = &transFalconExpanding;1053 1054	FalconSilence();1055	dmasound.hard = dmasound.soft;1056 1057	if (dmasound.hard.size == 16) {1058		/* the Falcon can play 16bit samples only in stereo */1059		dmasound.hard.stereo = 1;1060	}1061 1062	if (dmasound.hard.speed > 49170) {1063		/* we would need to squeeze the sound, but we won't do that */1064		dmasound.hard.speed = 49170;1065		divider = 1;1066		dmasound.trans_write = &transFalconNormal;1067	} else if (dmasound.hard.speed > 32780) {1068		dmasound.hard.speed = 49170;1069		divider = 1;1070	} else if (dmasound.hard.speed > 24585) {1071		dmasound.hard.speed = 32780;1072		divider = 2;1073	} else if (dmasound.hard.speed > 19668) {1074		dmasound.hard.speed = 24585;1075		divider = 3;1076	} else if (dmasound.hard.speed > 16390) {1077		dmasound.hard.speed = 19668;1078		divider = 4;1079	} else if (dmasound.hard.speed > 12292) {1080		dmasound.hard.speed = 16390;1081		divider = 5;1082	} else if (dmasound.hard.speed > 9834) {1083		dmasound.hard.speed = 12292;1084		divider = 7;1085	} else if (dmasound.hard.speed > 8195) {1086		dmasound.hard.speed = 9834;1087		divider = 9;1088	} else {1089		dmasound.hard.speed = 8195;1090		divider = 11;1091	}1092	tt_dmasnd.int_div = divider;1093 1094	/* Setup Falcon sound DMA for playback */1095	tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */1096	tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */1097	tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */1098	tt_dmasnd.cbar_dst = 0x0000;1099	tt_dmasnd.rec_track_select = 0;1100	tt_dmasnd.dac_src = 2; /* connect matrix to DAC */1101	tt_dmasnd.adc_src = 0; /* ADC Input = Mic */1102 1103	tt_dmasnd.mode = (dmasound.hard.stereo ?1104			  DMASND_MODE_STEREO : DMASND_MODE_MONO) |1105		((dmasound.hard.size == 8) ?1106		 DMASND_MODE_8BIT : DMASND_MODE_16BIT) |1107		DMASND_MODE_6KHZ;1108 1109	expand_bal = -dmasound.soft.speed;1110}1111 1112 1113static int FalconSetFormat(int format)1114{1115	int size;1116	/* Falcon sound DMA supports 8bit and 16bit modes */1117 1118	switch (format) {1119	case AFMT_QUERY:1120		return dmasound.soft.format;1121	case AFMT_MU_LAW:1122	case AFMT_A_LAW:1123	case AFMT_U8:1124	case AFMT_S8:1125		size = 8;1126		break;1127	case AFMT_S16_BE:1128	case AFMT_U16_BE:1129	case AFMT_S16_LE:1130	case AFMT_U16_LE:1131		size = 16;1132		break;1133	default: /* :-) */1134		size = 8;1135		format = AFMT_S8;1136	}1137 1138	dmasound.soft.format = format;1139	dmasound.soft.size = size;1140	if (dmasound.minDev == SND_DEV_DSP) {1141		dmasound.dsp.format = format;1142		dmasound.dsp.size = dmasound.soft.size;1143	}1144 1145	FalconInit();1146 1147	return format;1148}1149 1150 1151/* This is for the Falcon output *attenuation* in 1.5dB steps,1152 * i.e. output level from 0 to -22.5dB in -1.5dB steps.1153 */1154#define VOLUME_VOXWARE_TO_ATT(v) \1155	((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20)1156#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3)1157 1158 1159static int FalconSetVolume(int volume)1160{1161	dmasound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff);1162	dmasound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8);1163	tt_dmasnd.output_atten = dmasound.volume_left << 8 | dmasound.volume_right << 4;1164	return VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |1165	       VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8;1166}1167 1168 1169static void AtaPlayNextFrame(int index)1170{1171	char *start, *end;1172 1173	/* used by AtaPlay() if all doubts whether there really is something1174	 * to be played are already wiped out.1175	 */1176	start = write_sq.buffers[write_sq.front];1177	end = start+((write_sq.count == index) ? write_sq.rear_size1178					       : write_sq.block_size);1179	/* end might not be a legal virtual address. */1180	DMASNDSetEnd(virt_to_phys(end - 1) + 1);1181	DMASNDSetBase(virt_to_phys(start));1182	/* Since only an even number of samples per frame can1183	   be played, we might lose one byte here. (TO DO) */1184	write_sq.front = (write_sq.front+1) % write_sq.max_count;1185	write_sq.active++;1186	tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT;1187}1188 1189 1190static void AtaPlay(void)1191{1192	/* ++TeSche: Note that write_sq.active is no longer just a flag but1193	 * holds the number of frames the DMA is currently programmed for1194	 * instead, may be 0, 1 (currently being played) or 2 (pre-programmed).1195	 *1196	 * Changes done to write_sq.count and write_sq.active are a bit more1197	 * subtle again so now I must admit I also prefer disabling the irq1198	 * here rather than considering all possible situations. But the point1199	 * is that disabling the irq doesn't have any bad influence on this1200	 * version of the driver as we benefit from having pre-programmed the1201	 * DMA wherever possible: There's no need to reload the DMA at the1202	 * exact time of an interrupt but only at some time while the1203	 * pre-programmed frame is playing!1204	 */1205	atari_disable_irq(IRQ_MFP_TIMA);1206 1207	if (write_sq.active == 2 ||	/* DMA is 'full' */1208	    write_sq.count <= 0) {	/* nothing to do */1209		atari_enable_irq(IRQ_MFP_TIMA);1210		return;1211	}1212 1213	if (write_sq.active == 0) {1214		/* looks like there's nothing 'in' the DMA yet, so try1215		 * to put two frames into it (at least one is available).1216		 */1217		if (write_sq.count == 1 &&1218		    write_sq.rear_size < write_sq.block_size &&1219		    !write_sq.syncing) {1220			/* hmmm, the only existing frame is not1221			 * yet filled and we're not syncing?1222			 */1223			atari_enable_irq(IRQ_MFP_TIMA);1224			return;1225		}1226		AtaPlayNextFrame(1);1227		if (write_sq.count == 1) {1228			/* no more frames */1229			atari_enable_irq(IRQ_MFP_TIMA);1230			return;1231		}1232		if (write_sq.count == 2 &&1233		    write_sq.rear_size < write_sq.block_size &&1234		    !write_sq.syncing) {1235			/* hmmm, there were two frames, but the second1236			 * one is not yet filled and we're not syncing?1237			 */1238			atari_enable_irq(IRQ_MFP_TIMA);1239			return;1240		}1241		AtaPlayNextFrame(2);1242	} else {1243		/* there's already a frame being played so we may only stuff1244		 * one new into the DMA, but even if this may be the last1245		 * frame existing the previous one is still on write_sq.count.1246		 */1247		if (write_sq.count == 2 &&1248		    write_sq.rear_size < write_sq.block_size &&1249		    !write_sq.syncing) {1250			/* hmmm, the only existing frame is not1251			 * yet filled and we're not syncing?1252			 */1253			atari_enable_irq(IRQ_MFP_TIMA);1254			return;1255		}1256		AtaPlayNextFrame(2);1257	}1258	atari_enable_irq(IRQ_MFP_TIMA);1259}1260 1261 1262static irqreturn_t AtaInterrupt(int irq, void *dummy)1263{1264#if 01265	/* ++TeSche: if you should want to test this... */1266	static int cnt;1267	if (write_sq.active == 2)1268		if (++cnt == 10) {1269			/* simulate losing an interrupt */1270			cnt = 0;1271			return IRQ_HANDLED;1272		}1273#endif1274	spin_lock(&dmasound.lock);1275	if (write_sq_ignore_int && is_falcon) {1276		/* ++TeSche: Falcon only: ignore first irq because it comes1277		 * immediately after starting a frame. after that, irqs come1278		 * (almost) like on the TT.1279		 */1280		write_sq_ignore_int = 0;1281		goto out;1282	}1283 1284	if (!write_sq.active) {1285		/* playing was interrupted and sq_reset() has already cleared1286		 * the sq variables, so better don't do anything here.1287		 */1288		WAKE_UP(write_sq.sync_queue);1289		goto out;1290	}1291 1292	/* Probably ;) one frame is finished. Well, in fact it may be that a1293	 * pre-programmed one is also finished because there has been a long1294	 * delay in interrupt delivery and we've completely lost one, but1295	 * there's no way to detect such a situation. In such a case the last1296	 * frame will be played more than once and the situation will recover1297	 * as soon as the irq gets through.1298	 */1299	write_sq.count--;1300	write_sq.active--;1301 1302	if (!write_sq.active) {1303		tt_dmasnd.ctrl = DMASND_CTRL_OFF;1304		write_sq_ignore_int = 1;1305	}1306 1307	WAKE_UP(write_sq.action_queue);1308	/* At least one block of the queue is free now1309	   so wake up a writing process blocked because1310	   of a full queue. */1311 1312	if ((write_sq.active != 1) || (write_sq.count != 1))1313		/* We must be a bit carefully here: write_sq.count indicates the1314		 * number of buffers used and not the number of frames to be1315		 * played. If write_sq.count==1 and write_sq.active==1 that1316		 * means the only remaining frame was already programmed1317		 * earlier (and is currently running) so we mustn't call1318		 * AtaPlay() here, otherwise we'll play one frame too much.1319		 */1320		AtaPlay();1321 1322	if (!write_sq.active) WAKE_UP(write_sq.sync_queue);1323	/* We are not playing after AtaPlay(), so there1324	   is nothing to play any more. Wake up a process1325	   waiting for audio output to drain. */1326out:1327	spin_unlock(&dmasound.lock);1328	return IRQ_HANDLED;1329}1330 1331 1332/*** Mid level stuff *********************************************************/1333 1334 1335/*1336 * /dev/mixer abstraction1337 */1338 1339#define RECLEVEL_VOXWARE_TO_GAIN(v)	\1340	((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)1341#define RECLEVEL_GAIN_TO_VOXWARE(v)	(((v) * 20 + 2) / 3)1342 1343 1344static void __init TTMixerInit(void)1345{1346	atari_microwire_cmd(MW_LM1992_VOLUME(0));1347	dmasound.volume_left = 0;1348	atari_microwire_cmd(MW_LM1992_BALLEFT(0));1349	dmasound.volume_right = 0;1350	atari_microwire_cmd(MW_LM1992_BALRIGHT(0));1351	atari_microwire_cmd(MW_LM1992_TREBLE(0));1352	atari_microwire_cmd(MW_LM1992_BASS(0));1353}1354 1355static void __init FalconMixerInit(void)1356{1357	dmasound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;1358	dmasound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;1359}1360 1361static int AtaMixerIoctl(u_int cmd, u_long arg)1362{1363	int data;1364	unsigned long flags;1365	switch (cmd) {1366	    case SOUND_MIXER_READ_SPEAKER:1367		    if (is_falcon || MACH_IS_TT) {1368			    int porta;1369			    spin_lock_irqsave(&dmasound.lock, flags);1370			    sound_ym.rd_data_reg_sel = 14;1371			    porta = sound_ym.rd_data_reg_sel;1372			    spin_unlock_irqrestore(&dmasound.lock, flags);1373			    return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);1374		    }1375		    break;1376	    case SOUND_MIXER_WRITE_VOLUME:1377		    IOCTL_IN(arg, data);1378		    return IOCTL_OUT(arg, dmasound_set_volume(data));1379	    case SOUND_MIXER_WRITE_SPEAKER:1380		    if (is_falcon || MACH_IS_TT) {1381			    int porta;1382			    IOCTL_IN(arg, data);1383			    spin_lock_irqsave(&dmasound.lock, flags);1384			    sound_ym.rd_data_reg_sel = 14;1385			    porta = (sound_ym.rd_data_reg_sel & ~0x40) |1386				    (data < 50 ? 0x40 : 0);1387			    sound_ym.wd_data = porta;1388			    spin_unlock_irqrestore(&dmasound.lock, flags);1389			    return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);1390		    }1391	}1392	return -EINVAL;1393}1394 1395 1396static int TTMixerIoctl(u_int cmd, u_long arg)1397{1398	int data;1399	switch (cmd) {1400	    case SOUND_MIXER_READ_RECMASK:1401		return IOCTL_OUT(arg, 0);1402	    case SOUND_MIXER_READ_DEVMASK:1403		return IOCTL_OUT(arg,1404				 SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |1405				 (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0));1406	    case SOUND_MIXER_READ_STEREODEVS:1407		return IOCTL_OUT(arg, SOUND_MASK_VOLUME);1408	    case SOUND_MIXER_READ_VOLUME:1409		return IOCTL_OUT(arg,1410				 VOLUME_DB_TO_VOXWARE(dmasound.volume_left) |1411				 (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8));1412	    case SOUND_MIXER_READ_BASS:1413		return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.bass));1414	    case SOUND_MIXER_READ_TREBLE:1415		return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.treble));1416	    case SOUND_MIXER_READ_OGAIN:1417		return IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(dmasound.gain));1418	    case SOUND_MIXER_WRITE_BASS:1419		IOCTL_IN(arg, data);1420		return IOCTL_OUT(arg, dmasound_set_bass(data));1421	    case SOUND_MIXER_WRITE_TREBLE:1422		IOCTL_IN(arg, data);1423		return IOCTL_OUT(arg, dmasound_set_treble(data));1424	    case SOUND_MIXER_WRITE_OGAIN:1425		IOCTL_IN(arg, data);1426		return IOCTL_OUT(arg, dmasound_set_gain(data));1427	}1428	return AtaMixerIoctl(cmd, arg);1429}1430 1431static int FalconMixerIoctl(u_int cmd, u_long arg)1432{1433	int data;1434	switch (cmd) {1435	case SOUND_MIXER_READ_RECMASK:1436		return IOCTL_OUT(arg, SOUND_MASK_MIC);1437	case SOUND_MIXER_READ_DEVMASK:1438		return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER);1439	case SOUND_MIXER_READ_STEREODEVS:1440		return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC);1441	case SOUND_MIXER_READ_VOLUME:1442		return IOCTL_OUT(arg,1443			VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |1444			VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8);1445	case SOUND_MIXER_READ_CAPS:1446		return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT);1447	case SOUND_MIXER_WRITE_MIC:1448		IOCTL_IN(arg, data);1449		tt_dmasnd.input_gain =1450			RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 |1451			RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff);1452		fallthrough;	/* return set value */1453	case SOUND_MIXER_READ_MIC:1454		return IOCTL_OUT(arg,1455			RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |1456			RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8);1457	}1458	return AtaMixerIoctl(cmd, arg);1459}1460 1461static int AtaWriteSqSetup(void)1462{1463	write_sq_ignore_int = 0;1464	return 0 ;1465}1466 1467static int AtaSqOpen(fmode_t mode)1468{1469	write_sq_ignore_int = 1;1470	return 0 ;1471}1472 1473static int TTStateInfo(char *buffer, size_t space)1474{1475	int len = 0;1476	len += sprintf(buffer+len, "\tvol left  %ddB [-40...  0]\n",1477		       dmasound.volume_left);1478	len += sprintf(buffer+len, "\tvol right %ddB [-40...  0]\n",1479		       dmasound.volume_right);1480	len += sprintf(buffer+len, "\tbass      %ddB [-12...+12]\n",1481		       dmasound.bass);1482	len += sprintf(buffer+len, "\ttreble    %ddB [-12...+12]\n",1483		       dmasound.treble);1484	if (len >= space) {1485		printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ;1486		len = space ;1487	}1488	return len;1489}1490 1491static int FalconStateInfo(char *buffer, size_t space)1492{1493	int len = 0;1494	len += sprintf(buffer+len, "\tvol left  %ddB [-22.5 ... 0]\n",1495		       dmasound.volume_left);1496	len += sprintf(buffer+len, "\tvol right %ddB [-22.5 ... 0]\n",1497		       dmasound.volume_right);1498	if (len >= space) {1499		printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ;1500		len = space ;1501	}1502	return len;1503}1504 1505 1506/*** Machine definitions *****************************************************/1507 1508static SETTINGS def_hard_falcon = {1509	.format		= AFMT_S8,1510	.stereo		= 0,1511	.size		= 8,1512	.speed		= 81951513} ;1514 1515static SETTINGS def_hard_tt = {1516	.format	= AFMT_S8,1517	.stereo	= 0,1518	.size	= 8,1519	.speed	= 125171520} ;1521 1522static SETTINGS def_soft = {1523	.format	= AFMT_U8,1524	.stereo	= 0,1525	.size	= 8,1526	.speed	= 80001527} ;1528 1529static __initdata MACHINE machTT = {1530	.name		= "Atari",1531	.name2		= "TT",1532	.owner		= THIS_MODULE,1533	.dma_alloc	= AtaAlloc,1534	.dma_free	= AtaFree,1535	.irqinit	= AtaIrqInit,1536#ifdef MODULE1537	.irqcleanup	= AtaIrqCleanUp,1538#endif /* MODULE */1539	.init		= TTInit,1540	.silence	= TTSilence,1541	.setFormat	= TTSetFormat,1542	.setVolume	= TTSetVolume,1543	.setBass	= AtaSetBass,1544	.setTreble	= AtaSetTreble,1545	.setGain	= TTSetGain,1546	.play		= AtaPlay,1547	.mixer_init	= TTMixerInit,1548	.mixer_ioctl	= TTMixerIoctl,1549	.write_sq_setup	= AtaWriteSqSetup,1550	.sq_open	= AtaSqOpen,1551	.state_info	= TTStateInfo,1552	.min_dsp_speed	= 6258,1553	.version	= ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),1554	.hardware_afmts	= AFMT_S8,  /* h'ware-supported formats *only* here */1555	.capabilities	=  DSP_CAP_BATCH	/* As per SNDCTL_DSP_GETCAPS */1556};1557 1558static __initdata MACHINE machFalcon = {1559	.name		= "Atari",1560	.name2		= "FALCON",1561	.dma_alloc	= AtaAlloc,1562	.dma_free	= AtaFree,1563	.irqinit	= AtaIrqInit,1564#ifdef MODULE1565	.irqcleanup	= AtaIrqCleanUp,1566#endif /* MODULE */1567	.init		= FalconInit,1568	.silence	= FalconSilence,1569	.setFormat	= FalconSetFormat,1570	.setVolume	= FalconSetVolume,1571	.setBass	= AtaSetBass,1572	.setTreble	= AtaSetTreble,1573	.play		= AtaPlay,1574	.mixer_init	= FalconMixerInit,1575	.mixer_ioctl	= FalconMixerIoctl,1576	.write_sq_setup	= AtaWriteSqSetup,1577	.sq_open	= AtaSqOpen,1578	.state_info	= FalconStateInfo,1579	.min_dsp_speed	= 8195,1580	.version	= ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),1581	.hardware_afmts	= (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */1582	.capabilities	=  DSP_CAP_BATCH	/* As per SNDCTL_DSP_GETCAPS */1583};1584 1585 1586/*** Config & Setup **********************************************************/1587 1588 1589static int __init dmasound_atari_init(void)1590{1591	if (MACH_IS_ATARI && ATARIHW_PRESENT(PCM_8BIT)) {1592	    if (ATARIHW_PRESENT(CODEC)) {1593		dmasound.mach = machFalcon;1594		dmasound.mach.default_soft = def_soft ;1595		dmasound.mach.default_hard = def_hard_falcon ;1596		is_falcon = 1;1597	    } else if (ATARIHW_PRESENT(MICROWIRE)) {1598		dmasound.mach = machTT;1599		dmasound.mach.default_soft = def_soft ;1600		dmasound.mach.default_hard = def_hard_tt ;1601		is_falcon = 0;1602	    } else1603		return -ENODEV;1604	    if ((st_mfp.int_en_a & st_mfp.int_mk_a & 0x20) == 0)1605		return dmasound_init();1606	    else {1607		printk("DMA sound driver: Timer A interrupt already in use\n");1608		return -EBUSY;1609	    }1610	}1611	return -ENODEV;1612}1613 1614static void __exit dmasound_atari_cleanup(void)1615{1616	dmasound_deinit();1617}1618 1619module_init(dmasound_atari_init);1620module_exit(dmasound_atari_cleanup);1621 1622MODULE_DESCRIPTION("Atari TT and Falcon DMA Sound Driver");1623MODULE_LICENSE("GPL");1624