diff -Nuar linux-2.4.18/arch/arm/mach-sa1100/m62332.c linux-2.4.18p/arch/arm/mach-sa1100/m62332.c --- linux-2.4.18/arch/arm/mach-sa1100/m62332.c 2003-05-13 11:18:14.000000000 +0200 +++ linux-2.4.18p/arch/arm/mach-sa1100/m62332.c 2004-10-12 22:36:36.000000000 +0200 @@ -131,3 +131,5 @@ return 0; } +EXPORT_SYMBOL(m62332_senddata); + diff -Nuar linux-2.4.18/arch/arm/mach-sa1100/Makefile linux-2.4.18p/arch/arm/mach-sa1100/Makefile --- linux-2.4.18/arch/arm/mach-sa1100/Makefile 2003-05-13 11:18:14.000000000 +0200 +++ linux-2.4.18p/arch/arm/mach-sa1100/Makefile 2004-10-12 22:36:19.000000000 +0200 @@ -18,7 +18,7 @@ export-objs := assabet.o consus.o badge4.o dma-sa1100.o dma-sa1111.o \ flexanet.o freebird.o generic.o h3600.o \ huw_webpanel.o irq.o pcipool.o sa1111.o sa1111-pcibuf.o \ - system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o + system3.o yopy.o usb_ctl.o usb_recv.o usb_send.o m62332.o # These aren't present yet, and prevents a plain -ac kernel building. # hwtimer.o @@ -36,7 +36,7 @@ obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o endif -obj-$(CONFIG_SA1100_COLLIE) += collie.o m62332.o collie_battery.o collie_led.o collie_buzzer.o +obj-$(CONFIG_SA1100_COLLIE) += collie.o m62332.o collie_battery.o collie_led.o # Next, the SA1111 stuff. obj-$(CONFIG_SA1111) += sa1111.o dma-sa1111.o diff -Nuar linux-2.4.18/drivers/char/Makefile linux-2.4.18p/drivers/char/Makefile --- linux-2.4.18/drivers/char/Makefile 2003-05-13 11:18:18.000000000 +0200 +++ linux-2.4.18p/drivers/char/Makefile 2004-10-12 17:26:44.000000000 +0200 @@ -228,7 +228,7 @@ obj-y += joystick/js.o endif -obj-$(CONFIG_SA1100_COLLIE) += sharp_led.o sharp_kbdctl.o sharp_buzzer.o +obj-$(CONFIG_SA1100_COLLIE) += sharp_led.o sharp_kbdctl.o obj-$(CONFIG_DISCOVERY_LED) += sharp_led.o discovery_led.o obj-$(CONFIG_ARCH_PXA_POODLE) += sharp_led.o sharp_kbdctl.o sharpsl_led.o sharp_buzzer.o obj-$(CONFIG_ARCH_PXA_CORGI) += sharp_led.o sharpsl_led.o sharp_kbdctl.o corgi_rc.o sharp_buzzer.o diff -Nuar linux-2.4.18/drivers/sound/colliebuzzer.h linux-2.4.18p/drivers/sound/colliebuzzer.h --- linux-2.4.18/drivers/sound/colliebuzzer.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.18p/drivers/sound/colliebuzzer.h 2004-10-13 15:24:51.028208808 +0200 @@ -0,0 +1,756 @@ +unsigned short tap_data[] = { + 0x0000 , 0xff00 , 0xff00 , 0x0000 , + 0xff00 , 0x0000 , 0x0000 , 0x0100 , + 0x0000 , 0x0100 , 0x0000 , 0x0100 , + 0x0100 , 0x0000 , 0x0100 , 0x0100 , + 0x0100 , 0x0100 , 0x0100 , 0x0100 , + 0x0100 , 0x0100 , 0x0100 , 0x0100 , + 0x0100 , 0x0000 , 0x0100 , 0x0000 , + 0x0100 , 0xff00 , 0x0100 , 0x0000 , + 0x0100 , 0x0000 , 0x0000 , 0x0100 , + 0x0000 , 0x0100 , 0x0000 , 0x0100 , + 0x0000 , 0x0000 , 0x0000 , 0x0000 , + 0x0000 , 0x0100 , 0x0000 , 0x0100 , + 0x0000 , 0x0100 , 0x0700 , 0x1c00 , + 0xc800 , 0xd900 , 0x2b00 , 0x2700 , + 0xbf00 , 0xe000 , 0x0d00 , 0x1000 , + 0xf500 , 0xd700 , 0x0100 , 0x0a00 , + 0xfb00 , 0xfa00 , 0x2200 , 0x0100 , + 0xeb00 , 0x0300 , 0x0600 , 0x1600 , + 0xe500 , 0xf500 , 0x0d00 , 0x0a00 , + 0x0100 , 0xfb00 , 0x0000 , 0x0100 , + 0xf200 , 0x0400 , 0x0600 , 0x0000 , + 0xf100 , 0x0300 , 0x1200 , 0xfe00 , + 0xe900 , 0x0400 , 0x0100 , 0x0d00 , + 0xf500 , 0x0100 , 0x0100 , 0xfe00 , + 0x0100 , 0xfb00 , 0x0400 , 0xff00 , + 0xf700 , 0x0400 , 0x0000 , 0xfe00 , + 0x0200 , 0x0000 , 0x0100 , 0xfd00 , + 0x0000 , 0xff00 , 0x0200 , 0x0000 , + 0xff00 , 0x0000 , 0x0200 , 0xfc00 , + 0xfe00 , 0xff00 , 0x0100 , 0x0200 , + 0x0000 , 0xff00 , 0xfc00 , 0x0100 , + 0x0100 , 0x0100 , 0xff00 , 0x0000 , + 0x0300 , 0xfe00 , 0xfe00 , 0x0200 , + 0xff00 , 0x0000 , 0x0000 , 0xfe00 , + 0x0000 , 0xff00 , 0x0000 , 0x0000 , + 0x0000 , 0xff00 , 0x0000 , 0x0000 , + 0xff00 , 0xfe00 , 0xfd00 , 0x0100 , + 0x0000 , 0xfe00 , 0xff00 , 0xff00 , + 0x0000 , 0xff00 , 0x0100 , 0xfe00 , + 0xff00 , 0xff00 , 0x0000 , 0x0000 , + 0xfe00 , 0xff00 , 0x0100 , 0x0100 , + 0xff00 , 0x0100 , 0x0100 , 0xfe00 , + 0x0000 , 0x0000 , 0x0000 , 0x0100 , + 0x0000 , 0x0000 , 0xff00 , 0x0000 , + 0x0100 , 0x0000 , 0x0200 }; + + +unsigned short click_data[] = { + 0x0100 , 0x0100 , 0x0100 , 0x0000 , + 0x0100 , 0xff00 , 0x0100 , 0x0000 , + 0xff00 , 0xff00 , 0xff00 , 0x0000 , + 0xff00 , 0xff00 , 0xff00 , 0xff00 , + 0xff00 , 0xff00 , 0x0000 , 0xff00 , + 0xff00 , 0xff00 , 0x0000 , 0xff00 , + 0xff00 , 0xff00 , 0xff00 , 0x0100 , + 0x0000 , 0xff00 , 0xfe00 , 0x0100 , + 0xff00 , 0x0100 , 0xff00 , 0x0100 , + 0x0100 , 0x0300 , 0xff00 , 0xff00 , + 0xff00 , 0x0100 , 0x0100 , 0x0000 , + 0xfe00 , 0xfe00 , 0xfe00 , 0xfc00 , + 0xfe00 , 0x0100 , 0xfd00 , 0xff00 , + 0xff00 , 0xfc00 , 0xfe00 , 0xfd00 , + 0x0100 , 0xfe00 , 0x0100 , 0xf800 , + 0xfe00 , 0xfe00 , 0xfc00 , 0xe600 , + 0xdb00 , 0x2500 , 0xdb00 , 0xee00 , + 0xdb00 , 0x0600 , 0xeb00 , 0x1f00 , + 0x1e00 , 0xeb00 , 0xfe00 , 0x0000 , + 0xff00 , 0x1900 , 0xef00 , 0xf700 , + 0x2100 , 0xe400 , 0x0100 , 0x0600 , + 0xff00 , 0x0300 , 0xf900 , 0x0f00 , + 0xf600 , 0x0100 , 0xfe00 , 0xf900 , + 0x0500 , 0xf500 , 0x0600 , 0xfb00 , + 0x0800 , 0x0100 , 0x0300 , 0x0100 , + 0xf700 , 0xfa00 , 0xfd00 , 0xfc00 , + 0x0800 , 0xfb00 , 0x0500 , 0xfe00 , + 0xfc00 , 0xfc00 , 0xfe00 , 0x0400 , + 0xff00 , 0xff00 , 0x0500 , 0x0100 , + 0xfc00 , 0xff00 , 0xfe00 , 0xfb00 , + 0x0200 , 0x0200 , 0xff00 , 0xfe00 , + 0xfe00 , 0x0600 , 0xfb00 , 0xff00 , + 0xfc00 , 0x0600 , 0xfb00 , 0xff00 , + 0xff00 , 0x0100 , 0xff00 , 0x0200 , + 0xff00 , 0xfb00 , 0xff00 , 0x0200 , + 0xff00 , 0x0200 , 0x0100 , 0xfe00 , + 0xfe00 , 0x0100 , 0xfd00 , 0x0200 , + 0xfc00 , 0x0800 , 0xfe00 , 0xfe00 , + 0x0400 , 0xfc00 , 0xff00 , 0xfc00 , + 0x0500 , 0x0200 , 0x0800 , 0x0200 , + 0x0100 , 0xfe00 , 0x0100 , 0xff00 , + 0x0700 , 0xfb00 , 0xfc00 , 0x0100 , + 0xfe00 , 0xfc00 , 0x0b00 , 0xfb00 , + 0xfb00 , 0x0700 , 0xfb00 , 0xfb00 , + 0x0100 , 0xff00 , 0xfb00 , 0xfd00 , + 0x0000 , 0xfe00 , 0xfe00 , 0xff00 , + 0xfc00 , 0x0400 , 0x0000 , 0xfe00 , + 0xff00 , 0x0200 , 0xff00 , 0x0000 , + 0x0500 , 0x0100 , 0x0100 , 0x0100 , + 0x0100 , 0x0000 , 0x0300 , 0xfe00 , + 0xff00 , 0x0100 , 0x0100 , 0xfe00 , + 0x0000 , 0xff00 , 0x0100 , 0xff00 , + 0x0200 , 0xff00 , 0xff00 , 0xff00 , + 0xff00 , 0xfe00 , 0x0000 , 0xff00 , + 0xfe00 , 0xff00 , 0xfd00 , 0x0000 , + 0xff00 , 0xfe00 , 0xff00 , 0xfc00 , + 0x0100 , 0xfd00 , 0xff00 , 0xff00 , + 0x0200 , 0xff00 , 0x0100 , 0xff00 , + 0xfc00 , 0x0300 , 0xff00 , 0x0200 , + 0xff00 , 0x0100 , 0xff00 , 0x0100 , + 0xff00 , 0xff00 , 0x0100 , 0xfe00 , + 0x0300 , 0xfc00 , 0x0100 , 0xff00 , + 0x0100 , 0x0100 , 0x0100 , 0xfc00 , + 0xff00 , 0x0100 , 0x0100 , 0xfe00 , + 0x0100 , 0xff00 , 0x0100 , 0xfc00 , + 0x0100 , 0x0200 , 0xff00 , 0x0100 , + 0xff00 , 0xff00 , 0x0200 , 0xfd00 , + 0xfe00 , 0x0100 , 0xff00 , 0x0100 , + 0xfe00 , 0x0100 , 0x0300 , 0xfe00 , + 0x0300 , 0xfe00 , 0xff00 , 0x0100 , + 0xff00 , 0x0200 , 0xfd00 , 0x0000 , + 0xff00 , 0x0200 , 0xff00 , 0x0200 , + 0xff00 , 0x0100 , 0x0000 , 0xff00 , + 0x0200 , 0x0100 , 0x0000 , 0xff00 , + 0x0100 , 0xfe00 , 0x0200 , 0xfe00 , + 0xfe00 , 0x0100 , 0xfe00 , 0x0100 , + 0xfd00 , 0xff00 , 0xff00 , 0xfe00 , + 0xff00 , 0xfc00 , 0x0100 , 0xfe00 , + 0x0100 , 0xff00 , 0xfe00 , 0xff00 , + 0xff00 , 0xfe00 , 0x0100 , 0xfe00 , + 0x0100 , 0xff00 , 0x0100 , 0xfe00 , + 0xff00 , 0x0200 , 0xfe00 , 0x0000 , + 0x0100 , 0x0200 , 0xff00 , 0x0200 , + 0xff00 , 0x0000 , 0x0100 , 0x0100 , + 0xff00 , 0x0200 , 0xfe00 , 0xff00 , + 0xff00 , 0xff00 , 0x0100 , 0x0000 , + 0xff00 , 0x0100 , 0xff00 , 0x0000 , + 0x0100 , 0xff00 , 0xfe00 , 0xff00 , + 0xff00 , 0x0100 , 0xff00 , 0x0100 , + 0xfe00 , 0xff00 , 0xff00 , 0xff00 , + 0xfe00 , 0xff00 , 0xff00 , 0x0100 , + 0xff00 , 0x0200 , 0xff00 , 0x0100 , + 0xff00 , 0xff00 }; + + +unsigned short alarm_data[] = { + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x7fff , 0x7fff , 0x8000 , 0x8000 , // 9 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 0 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 1 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 2 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 3 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 4 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 5 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 6 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 7 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 8 + 0x7fff , 0x7fff , 0x7fff , 0x7fff , 0x8000 , 0x8000 , 0x8000 , 0x8000 , // 9 5 + +}; + + + + + +#define SHARP_BUZ_TOUCHSOUND 1 +#define SHARP_BUZ_KEYSOUND 2 +#define SHARP_BUZ_ALARM 11 +#define SHARP_BUZZER_MAKESOUND 0x5680 + +static int collie_ct_s16_buzzer(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + signed short *fp = (unsigned short *) &frame[*frameUsed]; + signed short *up = (unsigned short *) userPtr; + + DPRINTK("Collie_ct_s16 begin\n"); + + used = count = (userCount < frameLeft) ? userCount/2 : frameLeft/4; + + DPRINTK("Collie_ct_s16 begin count %d \n",count); + + while (count > 0) { + *fp++ = *up; + *fp++ = *up++; + count--; + } + + *frameUsed+=used*4; + DPRINTK("Collie_ct_s16 exit\n"); + return used*2; +} + + +static ssize_t sq_write_buzzer(int soundid) +{ + const char * src; + audio_stream_t *s = &output_stream; + u_char *dest; + ssize_t uUsed, bUsed, bLeft, uLeft, ret = 0; + + + if ((collie_tc_status!=NA) && (collie_tc_status!=PLAY)) + return -EPERM; + + collie_tc_status=PLAY; + + if (!s->buffers && sq_allocate_buffers(s)) { + return -ENOMEM; + } + + +#ifdef CONFIG_PM + /* Auto Power off cancel */ +// autoPowerCancel = 0; +#endif + DPRINTK("sq_write_buzzer: id:%d\n", soundid); + + switch (soundid) { + case SHARP_BUZ_TOUCHSOUND: + src=tap_data; + uLeft=176*2; + break; + case SHARP_BUZ_KEYSOUND: + src=click_data; + uLeft=360*2; + break; + case SHARP_BUZ_ALARM: + src=alarm_data; + uLeft=3072*2; + break; + default: + return 0; + } + DPRINTK("sq_write_buzzer: uLeft=%d\n", uLeft); + + collie_tc_mute_off(); + while (uLeft > 0) { + audio_buf_t *b = s->buf; + + ret = -ERESTARTSYS; + if (down_interruptible(&b->sem)) { + break; + } + + dest = b->start + b->size; + bUsed = 0; + bLeft = s->fragsize - b->size; + uUsed = collie_ct_s16_buzzer(src, uLeft, dest, &bUsed, bLeft); + cpu_cache_clean_invalidate_range((unsigned long)dest, + (unsigned long)(dest+(audio_fragsize)), 0); + + DPRINTK("back to sq_write_buzzer %p\n",dest); + + if (uUsed < 0) { + up(&b->sem); + return -EFAULT; + } + src += uUsed; + uLeft -= uUsed; + b->size += bUsed; + + if (b->size < s->fragsize) { + up(&b->sem); + break; + } + + /* Send current buffer to dma */ + sa1100_dma_queue_buffer(COLLIE_BUZZER_DMA_CHANNEL, + (void *) b, b->dma_addr, b->size); + + Collie_volume_set(4); + + b->size = 0; /* indicate that the buffer has been sent */ + NEXT_BUF(s, buf); + } + + DPRINTK("sq_write_buzzer: return\n"); + return ret; +} + + + + + + + diff -Nuar linux-2.4.18/drivers/sound/collie_ssp.c linux-2.4.18p/drivers/sound/collie_ssp.c --- linux-2.4.18/drivers/sound/collie_ssp.c 2003-05-13 11:18:37.000000000 +0200 +++ linux-2.4.18p/drivers/sound/collie_ssp.c 2004-10-13 15:05:36.000000000 +0200 @@ -9,6 +9,7 @@ * I/F : Synchronous serial port (SSP) TI mode * * Copyright (C) 2001 SHARP + * p.nis/dolOps messed around with it too! * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +25,18 @@ * 23-Oct-2001 SHARP * tune hardware control method * 12-Nov-2001 Lineo Japan, Inc. - * 14-Feb-2003 Sharp Corporation 8bit , GETOSPACE + * + * 26-Dec-2002 getospace added, some unneeded things removed + * + * 28-Dec-2002 cut out old stuff, reorder stuff + * + * 04-Jan-2003 put in getospace from lineo's collie-tc35143.c + * also added collie_record_on off, and exported these symbols + * + * 06-Jan-2003 if mixer ioctl SOUND_MIXER_READ_DEVMASK returns 0 as mask, + * than the headphone(/mic) is not connected + * + * */ #include #include @@ -35,7 +47,7 @@ #include #include #include -#include +#include #include #include #include @@ -48,38 +60,30 @@ #include #include #include -#include #include #include -#include +#include #include #include #undef DEBUG -//#define DEBUG #ifdef DEBUG #define DPRINTK( x... ) printk( ##x ) #else #define DPRINTK( x... ) #endif -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) || \ - defined(CONFIG_COLLIE_TR1) || defined(CONFIG_COLLIE_DEV) -#define COLLIE_TRY_ONE -#else -#undef COLLIE_TRY_ONE -#endif +#define COLLIE_TRY_ONE #ifdef COLLIE_TRY_ONE #ifndef GPIO_REMOCON_ADC_SW #define GPIO_REMOCON_ADC_SW GPIO_GPIO(18) #endif +static int collie_rc_irq; static DECLARE_WAIT_QUEUE_HEAD(audio_on); - - static inline void collie_rc_set_int_mode(void) { GPSR = GPIO_REMOCON_ADC_SW; @@ -91,14 +95,12 @@ } #endif - int collie_dmasound_irq = -1; -#define COLLIE_SOUND_DMA_CHANNEL (collie_dmasound_irq) +#define COLLIE_SOUND_DMA_CHANNEL (collie_dmasound_irq) #define SND_NDEVS 256 /* Number of supported devices */ #define SND_DEV_CTL 0 /* Control port /dev/mixer */ -#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM - synthesizer and MIDI output) */ +#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM synthesizer and MIDI output) */ #define SND_DEV_MIDIN 2 /* Raw midi access */ #define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */ #define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */ @@ -121,142 +123,25 @@ #endif /*** Some declarations ***********************************************/ -#define DMASND_TT 1 -#define DMASND_FALCON 2 -#define DMASND_AMIGA 3 -#define DMASND_AWACS 4 -#define DMASND_IRIS 5 -#define DMASND_COLLIE 6 -#define COLLIE_WAIT_AMP_ON 1 /* 10ms */ + #define COLLIE_WAIT_LCM_ACC_XEN 50 /* 500ms */ -#ifdef MODULE -static int catchRadius = 0; -#endif + static int collie_amp_init = 0; static int collie_dac_init = 0; -static int collie_op_shdn_on = 0; static int collie_resume = 0; static int collie_hard_mute = 1; static int collie_soft_mute = 1; static int collie_volume = 0; +int collie_recording=0; +static int playing=0; +static int headphone; -int collie_buzzer_volume = 0; - -#if 1 -static DECLARE_WAIT_QUEUE_HEAD(open_queue); +#define AUDIO_NBFRAGS_DEFAULT 64 +#define AUDIO_FRAGSIZE_DEFAULT 4096 -#define SIGNAL_RECEIVED (signal_pending(current)) -#define ONE_SECOND HZ /* in jiffies (100ths of a second) */ -#define SLEEP(queue, time_limit) \ - interruptible_sleep_on_timeout((wait_queue_head_t*)&queue, (time_limit)); -#define WAKE_UP(queue) (wake_up_interruptible((wait_queue_head_t*)&queue)) -#endif - -#define AUDIO_NBFRAGS_DEFAULT 8 -#define AUDIO_FRAGSIZE_DEFAULT 8192 - - -#define TRACE 0 -#if TRACE -#define TRACE_ON 1 -#define TRACE_SEM 0 -#define TRACE_SENDDATA 0 -#define TRACE_PM 1 -#define TRACE_AMP 1 -#define TRACE_DAC 1 -#define TRACE_OP_SHDN 1 -#define TRACE_WRITE 1 -#define TRACE_MUTE 1 -#define TRACE_CLOCK 1 -#define TRACE_PAIF 1 -#define TRACE_SSP 1 -#define TRACE_VOLUME 1 -#define TRACE_MIC 1 -#define TRACE_INTERRUPT 0 -int cLevel = 0; -char *pLevel[16] = { - /* 0 */"", - /* 1 */" ", - /* 2 */" ", - /* 3 */" ", - /* 4 */" ", - /* 5 */" ", - /* 6 */" ", - /* 7 */" ", - /* 8 */" ", - /* 9 */" ", - /* 10 */" ", - /* 11 */" ", - /* 12 */" ", - /* 13 */" ", - /* 14 */" ", - /* 15 */" " -}; -char * -indent(int level) -{ - int i; - return (level < 16 ) ? pLevel[level] : pLevel[15]; -} - -#define P_ID (current->tgid) -#define ENTER(f,fn) {if(f)printk("%d:%s+[%d]%s\n",jiffies,indent(cLevel),P_ID,(fn));cLevel++;} -#define LEAVE(f,fn) {cLevel--;if(f>1)printk("%d:%s-[%d]%s\n",jiffies,indent(cLevel),P_ID,(fn));} -#else /* ! TRACE */ -#define ENTER(f,fn) -#define LEAVE(f,fn) -#endif /* end TRACE */ -/* - * DAC power management - */ -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) || \ - defined(CONFIG_COLLIE_TR1) || defined(CONFIG_COLLIE_DEV) -#define DAC_OFF_WITH_DEVICE_OFF 1 -#undef HARD_MUTE_CTRL_DISABLE -#else -#undef DAC_OFF_WITH_DEVICE_OFF #undef HARD_MUTE_CTRL_DISABLE -#endif - - -#define TRY_DELAY_OFF -#ifdef TRY_DELAY_OFF /* H.Hayami SHARP 2001.12.19 */ -static DECLARE_WAIT_QUEUE_HEAD(delay_off); -struct semaphore df_sem; -/* - * delay execution - */ -static unsigned int DelayedFlag = 0; -#define DELAY_DAC_OFF 0x1 -#define DELAY_HARD_MUTE_ON 0x2 - -static inline void ResetDelayAll(void) -{ - DelayedFlag = 0; -} - -static inline int isDelayedExist(void) -{ - return DelayedFlag; -} - -static inline void SetDelay(unsigned int flag) -{ - DelayedFlag |= flag; -} - -static inline void ResetDelay(unsigned int flag) -{ - DelayedFlag &= ~flag; -} - -static inline unsigned int isDelayed(unsigned int flag) -{ - return DelayedFlag & flag; -} -#endif /* * Buffer Management @@ -268,6 +153,7 @@ dma_addr_t dma_addr; /* physical buffer address */ struct semaphore sem; /* down before touching the buffer */ int master; /* master owner for buffer allocation */ + u_int idx; /* buffer index, so that we know which buffer was sent last*/ } audio_buf_t; typedef struct { @@ -291,16 +177,6 @@ static volatile int audio_wr_refcount; /* nbr of concurrent open() for playback */ -static ssize_t (*ct_func)(const u_char *, size_t, u_char *, ssize_t *, ssize_t) = NULL; - -#ifdef MODULE -MODULE_PARM(catchRadius, "i"); -#endif -MODULE_PARM(numBufs, "i"); -MODULE_PARM(bufSize, "i"); - -#define min(x, y) ((x) < (y) ? (x) : (y)) - #define IOCTL_IN(arg, ret) \ do { int error = get_user(ret, (int *)(arg)); \ if (error) return error; \ @@ -310,11 +186,7 @@ /* * SA1110 GPIO (17) */ -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) -#define COLLIE_GPIO_OPSHDN GPIO_GPIO (17) /* AMP contorol */ -#else /* !CONFIG_COLLIE_TS && !CONFIG_COLLIE_TR0 */ #define COLLIE_GPIO_MIC GPIO_GPIO (17) /* MIC contorol */ -#endif /* !CONFIG_COLLIE_TS && !CONFIG_COLLIE_TR0 */ /* * DAC setup data @@ -352,122 +224,11 @@ ( LCM_ACC_XSEL1 | LCM_ACC_CLKSEL101 ) , }; +/*** "Translations" ************************************************************/ -/* 16 bit mu-law */ - -static short ulaw2dma16[] = { - -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, - -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, - -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, - -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, - -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, - -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, - -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, - -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, - -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, - -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, - -876, -844, -812, -780, -748, -716, -684, -652, - -620, -588, -556, -524, -492, -460, -428, -396, - -372, -356, -340, -324, -308, -292, -276, -260, - -244, -228, -212, -196, -180, -164, -148, -132, - -120, -112, -104, -96, -88, -80, -72, -64, - -56, -48, -40, -32, -24, -16, -8, 0, - 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, - 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, - 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, - 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, - 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, - 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, - 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, - 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, - 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, - 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, - 876, 844, 812, 780, 748, 716, 684, 652, - 620, 588, 556, 524, 492, 460, 428, 396, - 372, 356, 340, 324, 308, 292, 276, 260, - 244, 228, 212, 196, 180, 164, 148, 132, - 120, 112, 104, 96, 88, 80, 72, 64, - 56, 48, 40, 32, 24, 16, 8, 0, -}; - -/* 16 bit A-law */ - -static short alaw2dma16[] = { - -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, - -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, - -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, - -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, - -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, - -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, - -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, - -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, - -344, -328, -376, -360, -280, -264, -312, -296, - -472, -456, -504, -488, -408, -392, -440, -424, - -88, -72, -120, -104, -24, -8, -56, -40, - -216, -200, -248, -232, -152, -136, -184, -168, - -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, - -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, - -688, -656, -752, -720, -560, -528, -624, -592, - -944, -912, -1008, -976, -816, -784, -880, -848, - 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, - 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, - 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, - 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, - 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, - 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, - 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, - 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, - 344, 328, 376, 360, 280, 264, 312, 296, - 472, 456, 504, 488, 408, 392, 440, 424, - 88, 72, 120, 104, 24, 8, 56, 40, - 216, 200, 248, 232, 152, 136, 184, 168, - 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, - 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, - 688, 656, 752, 720, 560, 528, 624, 592, - 944, 912, 1008, 976, 816, 784, 880, 848, -}; - - - -/*** Translations ************************************************************/ - -static ssize_t collie_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t collie_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); -static ssize_t collie_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); static ssize_t collie_ct_s16(const u_char *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft); -static ssize_t collie_ct_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft); - -/*** Machine definitions *****************************************************/ - - -typedef struct { - int type; - void *(*dma_alloc)(unsigned int, int); - void (*dma_free)(void *, unsigned int); - int (*irqinit)(void); -#ifdef MODULE - void (*irqcleanup)(void); -#endif /* MODULE */ - void (*init)(void); - void (*silence)(void); - int (*setFormat)(int); - int (*setVolume)(int); - int (*setBass)(int); - int (*setTreble)(int); - int (*setGain)(int); - void (*play)(void); -} MACHINE; - /*** Low level stuff *********************************************************/ @@ -477,71 +238,28 @@ int stereo; /* 0 = mono, 1 = stereo */ int size; /* 8/16 bit*/ int speed; /* speed */ + int volume; } SETTINGS; -typedef struct { - ssize_t (*ct_ulaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_alaw)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u8)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16be)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_s16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); - ssize_t (*ct_u16le)(const u_char *, size_t, u_char *, ssize_t *, ssize_t); -} TRANS; - -struct sound_settings { - MACHINE mach; /* machine dependent things */ - SETTINGS hard; /* hardware settings */ - SETTINGS soft; /* software settings */ - SETTINGS dsp; /* /dev/dsp default settings */ - TRANS *trans; /* supported translations */ - int volume_left; /* volume (range is machine dependent) */ - int volume_right; - int bass; /* tone (range is machine dependent) */ - int treble; - int gain; - int minDev; /* minor device number currently open */ -}; - -static struct sound_settings sound; +static SETTINGS sound; #ifdef CONFIG_PM -extern int autoPowerCancel; +//extern int autoPowerCancel; #endif -int collie_main_volume; -extern int collie_under_recording; /* collie_buzzer.c */ -#define COLLE_RECORDING (collie_under_recording) static void Collie_Set_Volume(int volume); static int Collie_Get_Volume(void); -static void Collie_disable_sound(void); -#ifdef CONFIG_PM -#if 0 -static void Collie_clock_stop(void); -static void Collie_FS8KLPF_stop(void); -#endif -#endif static int CollieIrqInit(void); static int CollieGetSamp(void); -static void Collie_OP_SHDN_on(void); -static void Collie_OP_SHDN_off(void); -static void Collie_FS8KLPF_start(void); -#ifdef MODULE -static void CollieIrqCleanUp(void); -#endif /* MODULE */ -static void CollieSilence(void); static void Collie_DAC_sendword(int); -static void CollieInit(void); static int CollieSetFormat(int format); static void Collie_sq_interrupt(void*, int); static int sq_allocate_buffers(audio_stream_t*); static void sq_release_buffers(audio_stream_t*); +static inline void Collie_volume_init(void); +static void Collie_volume_set(int); /*** Mid level stuff *********************************************************/ -static void sound_silence(void); -static void sound_init(void); -static int sound_set_format(int format); static int sound_set_speed(int speed); static int sound_set_stereo(int stereo); @@ -572,468 +290,122 @@ static long long sound_lseek(struct file *file, long long offset, int orig); static inline int ioctl_return(int *addr, int value) { - ENTER(TRACE_ON,"ioctl_return"); if (value < 0) { - LEAVE(TRACE_ON,"ioctl_return"); return(value); } - - LEAVE(TRACE_ON,"ioctl_return"); return put_user(value, addr)? -EFAULT: 0; } - -/*** Config & Setup **********************************************************/ - - -void dmasound_init(void); -void dmasound_setup(char *str, int *ints); - - -/*** Translations ************************************************************/ - - -/* ++TeSche: radically changed for new expanding purposes... - * - * These two routines now deal with copying/expanding/translating the samples - * from user space into our buffer at the right frequency. They take care about - * how much data there's actually to read, how much buffer space there is and - * to convert samples into the right frequency/encoding. They will only work on - * complete samples so it may happen they leave some bytes in the input stream - * if the user didn't write a multiple of the current sample size. They both - * return the number of bytes they've used from both streams so you may detect - * such a situation. Luckily all programs should be able to cope with that. - * - * I think I've optimized anything as far as one can do in plain C, all - * variables should fit in registers and the loops are really short. There's - * one loop for every possible situation. Writing a more generalized and thus - * parameterized loop would only produce slower code. Feel free to optimize - * this in assembler if you like. :) - * - * I think these routines belong here because they're not yet really hardware - * independent, especially the fact that the Falcon can play 16bit samples - * only in stereo is hardcoded in both of them! - * - * ++geert: split in even more functions (one per format) - */ - -static ssize_t collie_ct_law(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - short *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma16: alaw2dma16; - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int val, stereo = sound.soft.stereo; - - ENTER(TRACE_ON,"collie_ct_law"); - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - if (!COLLE_RECORDING) { - while (count > 0) { - u_char data; - if (get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_law"); - return -EFAULT; - } - val = table[data]; - *p++ = val; /* Left Ch. */ - if (stereo) { - if (get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_law"); - return -EFAULT; - } - val = table[data]; - } - *p++ = val; /* Right Ch. */ - count--; - } - } else { - while (count > 0) { - u_char data; - int ave; - if (get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_law"); - return -EFAULT; - } - val = table[data]; - ave = val; /* Left Ch. */ - if (stereo) { - if (get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_law"); - return -EFAULT; - } - val = table[data]; - } - ave += val; /* Right Ch. */ - ave >>= 1; - *p++ = 0; /* Left Ch. */ - *p++ = ave; /* Right Ch. */ - count--; - } - } - *frameUsed += used * 4; - LEAVE(TRACE_ON,"collie_ct_law"); - return stereo? used * 2: used; -} - - -static ssize_t collie_ct_s8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int stereo = sound.soft.stereo; - short val; - - ENTER(TRACE_ON,"collie_ct_s8"); - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - if (!COLLE_RECORDING) { - while (count > 0) { - u_char data; - - if (get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_s8"); - return -EFAULT; - } - val = ( data - 0x80 ) << 8; - *p++ = val; /* Left Ch. */ - if ( stereo ) { - if ( get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_s8"); - return -EFAULT; - } - val = ( data - 0x80 ) << 8; - } - *p++ = val; /* Right Ch. */ - count--; - } - } else { - while (count > 0) { - u_char data; - int ave; - - if (get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_s8"); - return -EFAULT; - } - val = ( data - 0x80 ) << 8; - ave = val; /* Left Ch. */ - if ( stereo ) { - if ( get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_s8"); - return -EFAULT; - } - val = ( data - 0x80 ) << 8; - } - ave += val; /* Right Ch. */ - ave >>= 1; - *p++ = 0; /* Left Ch. */ - *p++ = ave; /* Right Ch. */ - count--; - } - } - *frameUsed += used * 4; - LEAVE(TRACE_ON,"collie_ct_s8"); - return stereo? used * 2: used; -} - - -static ssize_t collie_ct_u8(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) +static void wait_ms(int ten_ms) { - ssize_t count, used; - short *p = (short *) &frame[*frameUsed]; - int stereo = sound.soft.stereo; - short val; - - ENTER(TRACE_ON,"collie_ct_u8"); - frameLeft >>= 2; - if (stereo) - userCount >>= 1; - used = count = min(userCount, frameLeft); - if (!COLLE_RECORDING) { - while (count > 0) { - u_char data; - - if (get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_u8"); - return -EFAULT; - } - val = data; - *p++ = (val ^ 0x80) << 8; /* Left Ch. */ - if ( stereo ) { - if ( get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_u8"); - return -EFAULT; - } - val = data; - } - *p++ = (val ^ 0x80) << 8; /* Right Ch. */ - count--; - } - } else { - while (count > 0) { - u_char data; - int ave; - - if (get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_u8"); - return -EFAULT; - } - val = data; - ave = (val ^ 0x80) << 8; /* Left Ch. */ - if ( stereo ) { - if ( get_user(data, userPtr++)) { - LEAVE(TRACE_ON,"collie_ct_u8"); - return -EFAULT; - } - val = data; - } - ave += (val ^ 0x80) << 8; /* Right Ch. */ - ave >>= 1; - *p++ = 0; /* Left Ch. */ - *p++ = ave; /* Right Ch. */ - count--; - } - } - *frameUsed += used * 4; - LEAVE(TRACE_ON,"collie_ct_u8"); - return stereo? used * 2: used; + schedule_timeout(ten_ms); } +/*** Translation ************************************************************/ static ssize_t collie_ct_s16(const u_char *userPtr, size_t userCount, u_char frame[], ssize_t *frameUsed, ssize_t frameLeft) { ssize_t count, used; - int stereo = sound.soft.stereo; short *fp = (short *) &frame[*frameUsed]; + short *up = (short *) userPtr; - ENTER(TRACE_ON,"collie_ct_s16"); frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - if (!stereo) { - short *up = (short *) userPtr; - while (count > 0) { - short data; - if (get_user(data, up++)) { - LEAVE(TRACE_ON,"collie_ct_s16"); - return -EFAULT; - } - *fp++ = (!COLLE_RECORDING) ? data : 0; /* Left Ch. */ - *fp++ = data; - count--; + userCount >>= 2; + used = count = (userCount < frameLeft) ? userCount : frameLeft; + + while (count > 0) { + + short data; + if (get_user(data, up++)) { + return -EFAULT; } - } else { - short *up = (short *) userPtr; - while (count > 0) { - short data; - short temp; - if (get_user(data, up++)) { - LEAVE(TRACE_ON,"collie_ct_s16"); - return -EFAULT; - } - if (get_user(temp, up++)) { - LEAVE(TRACE_ON,"collie_ct_s16"); - return -EFAULT; - } - if (!COLLE_RECORDING) { - *fp++ = data; /* Left Ch. */ - *fp++ = temp; /* Right Ch. */ - } else { - data >>= 1; - data += (temp >> 1); - *fp++ = 0; /* Left Ch. */ - *fp++ = data; /* Right Ch. */ - } - count--; + if (!collie_recording) *fp++ = data; + else *fp++=0; + + if (get_user(data, up++)) { + return -EFAULT; } + *fp++ = data; + count--; } + *frameUsed += used * 4; - LEAVE(TRACE_ON,"collie_ct_s16"); - return stereo? used * 4: used * 2; + return used * 4; } -static ssize_t collie_ct_u16(const u_char *userPtr, size_t userCount, - u_char frame[], ssize_t *frameUsed, - ssize_t frameLeft) -{ - ssize_t count, used; - int mask = (sound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); - int stereo = sound.soft.stereo; - short *fp = (short *) &frame[*frameUsed]; - short *up = (short *) userPtr; +/*** HARDWARE dependent stuff *********************************************************/ - ENTER(TRACE_ON,"collie_ct_u16"); - frameLeft >>= 2; - userCount >>= (stereo? 2: 1); - used = count = min(userCount, frameLeft); - if (!COLLE_RECORDING) { - while (count > 0) { - int data; - int temp; - if (get_user(data, up++)) { - LEAVE(TRACE_ON,"collie_ct_u16"); - return -EFAULT; - } - data ^= mask; - *fp++ = data; /* Left Ch. */ - if (stereo) { - if (get_user(temp, up++)) { - LEAVE(TRACE_ON,"collie_ct_u16"); - return -EFAULT; - } - temp ^= mask; - data = temp; - data ^= mask; - } - *fp++ = data; /* Right Ch. */ - count--; - } +static inline void Collie_DAC_sendbit(int bit_data) +{ + if (bit_data & 1) { + LCM_GPO |= (LCM_GPIO_DAC_SDATA); } else { - while (count > 0) { - int data; - int temp; - int ave; - if (get_user(data, up++)) { - LEAVE(TRACE_ON,"collie_ct_u16"); - return -EFAULT; - } - data ^= mask; - ave = data; /* Left Ch. */ - if (stereo) { - if (get_user(temp, up++)) { - LEAVE(TRACE_ON,"collie_ct_u16"); - return -EFAULT; - } - temp ^= mask; - data = temp; - data ^= mask; - } - ave += data; - ave >>= 1; - *fp++ = 0; /* Left Ch. */ - *fp++ = ave; /* Right Ch. */ - count--; - } + LCM_GPO &= ~(LCM_GPIO_DAC_SDATA); } - *frameUsed += used * 4; - LEAVE(TRACE_ON,"collie_ct_u16"); - return stereo? used * 4: used * 2; -} -static TRANS transCollie = { - collie_ct_law, collie_ct_law, collie_ct_s8, collie_ct_u8, - collie_ct_s16, collie_ct_u16, collie_ct_s16, collie_ct_u16 -}; + udelay(1); + LCM_GPO |= (LCM_GPIO_DAC_SCK); -/*** Low level stuff *********************************************************/ + udelay(1); + LCM_GPO &= ~(LCM_GPIO_DAC_SCK); + udelay(1); + LCM_GPO &= ~(LCM_GPIO_DAC_SDATA); + udelay(1); +} -static void Collie_Set_Volume(int volume) +static void Collie_DAC_sendword(int data) { - ENTER(TRACE_ON,"Collie_Set_Volume"); - - sound.volume_left = volume & 0xff; - if ( sound.volume_left > 100 ) sound.volume_left = 100; - - collie_main_volume = sound.volume_left; - - sound.volume_right = ( volume & 0xff00 >> 8); - if ( sound.volume_right > 100 ) sound.volume_right = 100; - LEAVE(TRACE_ON,"Collie_Set_Volume"); + int i; - collie_buzzer_volume = sound.volume_right; +#if defined(CONFIG_COLLIE_PCM1741) + + LCM_GPO &= ~(LCM_GPIO_DAC_SCK); + udelay(1); + LCM_GPO |= (LCM_GPIO_DAC_SLOAD); + udelay(1); -} + for (i = 0; i < 16; i++) + Collie_DAC_sendbit(data >> (15 - i)); + LCM_GPO &= ~(LCM_GPIO_DAC_SLOAD); + udelay(2); -static int Collie_Get_Volume(void) -{ - ENTER(TRACE_ON,"Collie_Get_Volume"); - LEAVE(TRACE_ON,"Collie_Get_Volume"); - return ( sound.volume_right << 8 | sound.volume_left ); -} +#elif defined(CONFIG_COLLIE_PCM1717) + + LCM_GPO &= ~(LCM_GPIO_DAC_SLOAD); + udelay(1000); + LCM_GPO |= (LCM_GPIO_DAC_SLOAD); + udelay(1000); + LCM_GPO &= ~(LCM_GPIO_DAC_SCK); + udelay(1000); -static void wait_ms(int ten_ms) -{ - ENTER(TRACE_ON,"wait_ms"); - LEAVE(TRACE_ON,"wait_ms"); - schedule_timeout(ten_ms); -} + for (i = 0; i < 16; i++) + Collie_DAC_sendbit(data >> (15 - i)); -static inline void Collie_AMP_off(void) -{ -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_AMP,"Collie_AMP_off"); -#if 0 /* OBSOLETED: power controled by only OP_SHDN */ - /* Set up TC35143 GPIO I/O Direction (GPIO4 output mode) */ - ucb1200_set_io_direction(TC35143_GPIO_AMP_ON, - TC35143_IODIR_OUTPUT); - /* AMP OFF */ - ucb1200_set_io(TC35143_GPIO_AMP_ON, - TC35143_IODAT_LOW); - collie_amp_init = 0; -#endif /* 0 */ - LEAVE(TRACE_AMP,"Collie_AMP_off"); -#endif /* CONFIG_COLLIE_TS || CONFIG_COLLIE_TR0 */ -} - -static inline void Collie_AMP_on(void) -{ -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_AMP,"Collie_AMP_on"); -// if (!collie_amp_init) { - /* Set up TC35143 GPIO I/O Direction (GPIO4 output mode) */ - ucb1200_set_io_direction(TC35143_GPIO_AMP_ON, - TC35143_IODIR_OUTPUT); - /* AMP ON */ - ucb1200_set_io(TC35143_GPIO_AMP_ON, TC35143_IODAT_HIGH); - SCP_REG_GPWR |= SCP_AMP_ON; - wait_ms(COLLIE_WAIT_AMP_ON); - collie_amp_init = 1; -// } - LEAVE(TRACE_AMP,"Collie_AMP_on"); -#endif /* CONFIG_COLLIE_TS || CONFIG_COLLIE_TR0 */ + LCM_GPO &= ~(LCM_GPIO_DAC_SLOAD); + udelay(1000); + LCM_GPO |= (LCM_GPIO_DAC_SLOAD); + udelay(1000); + LCM_GPO &= ~(LCM_GPIO_DAC_SLOAD); + udelay(1000); +#endif } -static inline void Collie_AMP_init(void) -{ -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_AMP,"Collie_AMP_init"); - Collie_AMP_off(); - LEAVE(TRACE_AMP,"Collie_AMP_init"); -#endif /* CONFIG_COLLIE_TS || CONFIG_COLLIE_TR0 */ -} static inline void Collie_DAC_off(void) { - ENTER(TRACE_DAC,"Collie_DAC_off"); - if (!COLLE_RECORDING) { - /* DAC OFF */ - LCM_GPD &= ~(LCM_GPIO_DAC_ON); /* set up output */ - LCM_GPO &= ~(LCM_GPIO_DAC_ON); - - /* LoCoMo GPIO disable */ - LCM_GPE &= ~(LCM_GPIO_DAC_ON); - collie_dac_init = 0; - } - LEAVE(TRACE_DAC,"Collie_DAC_off"); + /* DAC OFF */ + LCM_GPD &= ~(LCM_GPIO_DAC_ON); /* set up output */ + LCM_GPO &= ~(LCM_GPIO_DAC_ON); + /* LoCoMo GPIO disable */ + LCM_GPE &= ~(LCM_GPIO_DAC_ON); + collie_dac_init = 0; } static inline void Collie_DAC_on(void) { - ENTER(TRACE_DAC,"Collie_DAC_on"); -// if (!collie_dac_init) { if (!(LCM_GPO & LCM_GPIO_DAC_ON)) { /* LoCoMo GPIO enable */ LCM_GPE &= ~LCM_GPIO_DAC_ON; @@ -1049,24 +421,10 @@ schedule(); } } -// } - LEAVE(TRACE_DAC,"Collie_DAC_on"); -} - -#ifdef TRY_DELAY_OFF /* H.Hayami SHARP */ -static inline void Collie_DAC_delay_off(void) -{ - ENTER(TRACE_DAC,"Collie_DAC_deleay_off"); - down(&df_sem); - SetDelay(DELAY_DAC_OFF); - up(&df_sem); - LEAVE(TRACE_DAC,"Collie_DAC_delay_off"); } -#endif static inline void Collie_DAC_init(void) { - ENTER(TRACE_DAC,"Collie_DAC_init"); /* LoCoMo GPIO enable */ LCM_GPE &= ~(LCM_GPIO_DAC_SDATA | LCM_GPIO_DAC_SCK | LCM_GPIO_DAC_SLOAD); @@ -1075,7 +433,6 @@ ~(LCM_GPIO_DAC_SDATA | LCM_GPIO_DAC_SCK | LCM_GPIO_DAC_SLOAD); #if defined(CONFIG_COLLIE_PCM1741) - Collie_DAC_sendword(DAC_REG16_SetupData); /* register16 */ Collie_DAC_sendword(DAC_REG17_SetupData); /* register17 */ Collie_DAC_sendword(DAC_REG18_SetupData); /* register18 */ @@ -1083,78 +440,53 @@ Collie_DAC_sendword(DAC_REG20_SetupData); /* register20 */ //// Collie_DAC_sendword(DAC_REG21_SetupData); /* register21 */ Collie_DAC_sendword(DAC_REG22_SetupData); /* register22 */ - #elif defined(CONFIG_COLLIE_PCM1717) - Collie_DAC_sendword(DAC_MODE0_SetupData); /* MODE0 */ Collie_DAC_sendword(DAC_MODE1_SetupData); /* MODE1 */ Collie_DAC_sendword(DAC_MODE2_SetupData); /* MODE2 */ Collie_DAC_sendword(DAC_MODE3_SetupData); /* MODE3 */ - #endif - /* LoCoMo GPIO disable */ LCM_GPE &= ~(LCM_GPIO_DAC_SDATA | LCM_GPIO_DAC_SCK | LCM_GPIO_DAC_SLOAD); - LEAVE(TRACE_DAC,"Collie_DAC_init"); } static inline void Collie_soft_DAC_on(void) { #if defined(CONFIG_COLLIE_PCM1741) - ENTER(TRACE_DAC, "Collie_soft_DAC_on"); Collie_DAC_sendword(DAC_REG19_DACOn); /* register19 */ - LEAVE(TRACE_DAC, "Collie_soft_DAC_on"); #endif /* CONFIG_COLLIE_PCM1741 */ } static inline void Collie_soft_DAC_off(void) { #if defined(CONFIG_COLLIE_PCM1741) - ENTER(TRACE_DAC, "Collie_soft_DAC_off"); Collie_DAC_sendword(DAC_REG19_DACOff); /* register19 */ - LEAVE(TRACE_DAC, "Collie_soft_DAC_off"); -#endif /* CONFIG_COLLIE_PCM1741 */ -} - -static inline void Collie_soft_mute_init(void) -{ -#if defined(CONFIG_COLLIE_PCM1741) - ENTER(TRACE_MUTE, "Collie_soft_mute_init"); - Collie_DAC_sendword(DAC_REG18_MuteOn); /* register18 */ - collie_soft_mute = 1; - LEAVE(TRACE_MUTE, "Collie_soft_mute_init"); #endif /* CONFIG_COLLIE_PCM1741 */ } static inline void Collie_soft_mute_on(void) { #if defined(CONFIG_COLLIE_PCM1741) - ENTER(TRACE_MUTE, "Collie_soft_mute_on"); if (!collie_soft_mute) { Collie_DAC_sendword(DAC_REG18_MuteOn); /* register18 */ collie_soft_mute = 1; } - LEAVE(TRACE_MUTE, "Collie_soft_mute_on"); #endif /* CONFIG_COLLIE_PCM1741 */ } static inline void Collie_soft_mute_off(void) { #if defined(CONFIG_COLLIE_PCM1741) - ENTER(TRACE_MUTE, "Collie_soft_mute_off"); if (collie_soft_mute) { Collie_DAC_sendword(DAC_REG18_MuteOff); /* register18 */ collie_soft_mute = 0; } - LEAVE(TRACE_MUTE, "Collie_soft_mute_off"); #endif /* CONFIG_COLLIE_PCM1741 */ } static inline void Collie_hard_mute_init(void) { -#if !defined(CONFIG_COLLIE_TS) && !defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_MUTE, "Collie_hard_mute_init"); SCP_REG_GPCR |= (SCP_GPCR_PA14 | SCP_GPCR_PA15); #ifdef HARD_MUTE_CTRL_DISABLE SCP_REG_GPWR |= (SCP_GPCR_PA14 | SCP_GPCR_PA15); @@ -1162,84 +494,107 @@ SCP_REG_GPWR &= ~(SCP_GPCR_PA14 | SCP_GPCR_PA15); #endif /* HARD_MUTE_CTRL_DISABLE */ collie_hard_mute = 1; -#if !defined(CONFIG_COLLIE_TR1) && !defined(CONFIG_COLLIE_DEV) + { int time = jiffies + 5; while (jiffies <= time) schedule(); } -#endif - LEAVE(TRACE_MUTE, "Collie_hard_mute_init"); -#endif /* !CONFIG_COLLIE_TS && !CONFIG_COLLIE_TR0 */ } static inline void Collie_hard_mute_on(void) { -#if !defined(CONFIG_COLLIE_TS) && !defined(CONFIG_COLLIE_TR0) #ifndef HARD_MUTE_CTRL_DISABLE - ENTER(TRACE_MUTE, "Collie_hard_mute_on"); if (!collie_hard_mute) { SCP_REG_GPWR &= ~(SCP_GPCR_PA14 | SCP_GPCR_PA15); collie_hard_mute = 1; -#if !defined(CONFIG_COLLIE_TR1) && !defined(CONFIG_COLLIE_DEV) { int time = jiffies + 5; while (jiffies <= time) schedule(); } -#endif } - LEAVE(TRACE_MUTE, "Collie_hard_mute_on"); #endif /* HARD_MUTE_CTRL_DISABLE */ -#endif /* !CONFIG_COLLIE_TS && !CONFIG_COLLIE_TR0 */ } static inline void Collie_hard_mute_off(void) { -#if !defined(CONFIG_COLLIE_TS) && !defined(CONFIG_COLLIE_TR0) #ifndef HARD_MUTE_CTRL_DISABLE - ENTER(TRACE_MUTE, "Collie_hard_mute_off"); if (collie_hard_mute) { - if (!COLLE_RECORDING) SCP_REG_GPWR |= (SCP_GPCR_PA14 | SCP_GPCR_PA15); - else - SCP_REG_GPWR |= (SCP_GPCR_PA15); collie_hard_mute = 0; -#if !defined(CONFIG_COLLIE_TR1) && !defined(CONFIG_COLLIE_DEV) { int i; for (i=0; i<=1000; i++) { udelay(1); } } -#endif } - LEAVE(TRACE_MUTE, "Collie_hard_mute_off"); #endif /* HARD_MUTE_CTRL_DISABLE */ -#endif /* !CONFIG_COLLIE_TS && !CONFIG_COLLIE_TR0 */ -} - -#ifdef TRY_DELAY_OFF /* H.Hayami SHARP 2001.12.19 */ -static inline void Collie_hard_mute_delay_on(void) -{ - ENTER(TRACE_MUTE, "Collie_hard_mute_delay_on"); - down(&df_sem); - SetDelay(DELAY_HARD_MUTE_ON); - up(&df_sem); - LEAVE(TRACE_MUTE, "Collie_hard_mute_delay_on"); } -#endif -static inline void Collie_audio_clock_init(void) +static inline void Collie_hard_mute_left_on(void) +{ +#ifndef HARD_MUTE_CTRL_DISABLE +// if (!collie_hard_mute) { + SCP_REG_GPWR &= ~(SCP_GPCR_PA14); + { + int time = jiffies + 5; + while (jiffies <= time) + schedule(); + } +// } +#endif /* HARD_MUTE_CTRL_DISABLE */ +} + +static inline void Collie_hard_mute_left_off(void) +{ +#ifndef HARD_MUTE_CTRL_DISABLE +// if (collie_hard_mute) { + SCP_REG_GPWR |= (SCP_GPCR_PA14); + { + int i; + for (i=0; i<=1000; i++) { + udelay(1); + } + } +// } +#endif /* HARD_MUTE_CTRL_DISABLE */ +} + + +static int CollieGetSamp(void) +{ + switch (sound.speed) { + case 8000: + return clock_set_data[7]; + case 44100: + return clock_set_data[0]; + case 22050: + return clock_set_data[1]; + case 11025: + return clock_set_data[2]; + case 48000: + return clock_set_data[3]; + case 32000: + return clock_set_data[4]; + case 24000: + return clock_set_data[5]; + case 16000: + return clock_set_data[6]; + default: + printk("Collie sound: Illegal sound rate %d\n", sound.speed); + return clock_set_data[7]; + } +} + +static inline void Collie_audio_clock_init(void) { - ENTER(TRACE_CLOCK, "Collie_audio_clock_init"); LCM_ACC = 0; - LEAVE(TRACE_CLOCK, "Collie_audio_clock_init"); } static inline void Collie_audio_clock_on(void) { - ENTER(TRACE_CLOCK, "Collie_audio_clock_on"); /* LoCoMo Audio clock on */ LCM_ACC = CollieGetSamp(); barrier(); @@ -1248,263 +603,58 @@ LCM_ACC |= LCM_ACC_XEN; barrier(); LCM_ACC |= (LCM_ACC_MCLKEN | LCM_ACC_64FSEN); - LEAVE(TRACE_CLOCK, "Collie_audio_clock_on"); } static inline void Collie_audio_clock_off(void) { - ENTER(TRACE_CLOCK, "Collie_audio_clock_off"); /* LoCoMo Audio clock off */ LCM_ACC &= ~(LCM_ACC_XEN | LCM_ACC_MCLKEN | LCM_ACC_64FSEN); barrier(); LCM_ACC &= ~(LCM_ACC_XON); - LEAVE(TRACE_CLOCK, "Collie_audio_clock_off"); -} - -static inline void Collie_paif_init(void) -{ - ENTER(TRACE_PAIF, "Collie_paif_init"); - // LCM_PAIF = (LCM_PAIF_SCINV | LCM_PAIF_LRCRST); - LCM_PAIF = (LCM_PAIF_LRCRST); - LEAVE(TRACE_PAIF, "Collie_paif_init"); } static inline void Collie_paif_on(void) { - ENTER(TRACE_PAIF, "Collie_paif_on"); LCM_PAIF = (LCM_PAIF_SCINV | LCM_PAIF_LRCRST); LCM_PAIF &= ~(LCM_PAIF_LRCRST); LCM_PAIF |= (LCM_PAIF_SCEN | LCM_PAIF_LRCEN); - LEAVE(TRACE_PAIF, "Collie_paif_on"); } static inline void Collie_paif_off(void) { - ENTER(TRACE_PAIF, "Collie_paif_off"); - // LCM_PAIF = (LCM_PAIF_SCINV | LCM_PAIF_LRCRST); LCM_PAIF = (LCM_PAIF_LRCRST); - LEAVE(TRACE_PAIF, "Collie_paif_off"); } static inline void Collie_MIC_init(void) { -#if !defined(CONFIG_COLLIE_TS) && !defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_MIC, "Collie_MIC_init"); /* MIC to GPIO 17 */ /* alternate functions for the GPIOs */ - GAFR &= ~( COLLIE_GPIO_MIC ); - + GAFR &= ~( COLLIE_GPIO_MIC ); /* Set the direction: 17 output */ GPDR |= ( COLLIE_GPIO_MIC ); - -#if defined(CONFIG_COLLIE_TR1) - /* Set pin level (Low) */ - GPCR = ( COLLIE_GPIO_MIC ); -#else /* Set pin level (High) */ GPSR = ( COLLIE_GPIO_MIC ); -#endif - LEAVE(TRACE_MIC, "Collie_MIC_init"); -#endif /* !CONFIG_COLLIE_TS && !CONFIG_COLLIE_TR0 */ } static inline void Collie_MIC_on(void) { -#if !defined(CONFIG_COLLIE_TS) && !defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_MIC, "Collie_MIC_on"); -#if defined(CONFIG_COLLIE_TR1) - GPSR = ( COLLIE_GPIO_MIC ); -#else GPCR = ( COLLIE_GPIO_MIC ); -#endif - LEAVE(TRACE_MIC, "Collie_MIC_on"); -#endif /* !CONFIG_COLLIE_TS && !CONFIG_COLLIE_TR0 */ } static inline void Collie_MIC_off(void) { -#if !defined(CONFIG_COLLIE_TS) && !defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_MIC, "Collie_MIC_off"); - if (!COLLE_RECORDING) { -#if defined(CONFIG_COLLIE_TR1) - GPCR = ( COLLIE_GPIO_MIC ); -#else - GPSR = ( COLLIE_GPIO_MIC ); -#endif - } - LEAVE(TRACE_MIC, "Collie_MIC_off"); -#endif /* !CONFIG_COLLIE_TS && !CONFIG_COLLIE_TR0 */ -} - -static inline void Collie_volume_init(void) -{ - ENTER(TRACE_VOLUME, "Collie_volume_init"); - m62332_senddata(0, M62332_EVR_CH); - collie_volume = 0; - LEAVE(TRACE_VOLUME, "Collie_volume_init"); -} - -static inline void Collie_volume_on(void) -{ - ENTER(TRACE_VOLUME, "Collie_volume_on"); - if (collie_volume != sound.volume_left) { - //Collie_hard_mute_on(); - m62332_senddata(0xff * sound.volume_left / 100, M62332_EVR_CH); - //Collie_hard_mute_off(); - collie_volume = sound.volume_left; - } - LEAVE(TRACE_VOLUME, "Collie_volume_on"); -} - -static inline void Collie_volume_off(void) -{ - ENTER(TRACE_VOLUME, "Collie_volume_off"); - if (collie_volume) { - //Collie_hard_mute_on(); - m62332_senddata(0, M62332_EVR_CH); - //Collie_hard_mute_off(); - collie_volume = 0; - } - LEAVE(TRACE_VOLUME, "Collie_volume_off"); -} - -#define VOL_THRES 40 -static void Collie_volume_half_adjust(void) -{ - int volume = collie_volume; - ENTER(TRACE_VOLUME, "Collie_volume_half_adjust"); - if (collie_volume > sound.volume_left) { - /* volume down */ - if (collie_volume > VOL_THRES) { - if (sound.volume_left > VOL_THRES) { - volume = (collie_volume + sound.volume_left)/2; - if (volume == collie_volume) { - volume = sound.volume_left; - } - } else { - volume = (collie_volume + VOL_THRES)/2; - if (volume == collie_volume) { - volume = VOL_THRES; - } - } - } else { - /* we can pull down without noise */ - volume = sound.volume_left; - } - } else if (collie_volume < sound.volume_left) { - /* volume up */ - if (sound.volume_left > VOL_THRES) { - if (collie_volume < VOL_THRES) { - /* we can pull up to VOL_THRES without noise */ - volume = VOL_THRES;; - } else { - volume = (collie_volume + sound.volume_left)/2; - if (volume == collie_volume) { - volume = sound.volume_left; - } - } - } else { - /* we can pull up without noise */ - volume = sound.volume_left; - } - } - if (collie_volume != volume) { - m62332_senddata(0xff * volume / 100, M62332_EVR_CH); - collie_volume = volume; - } - LEAVE(TRACE_VOLUME, "Collie_volume_half_adjust"); -} - -static void Collie_volume_half_off(void) -{ - int volume; - int delta = 1; - ENTER(TRACE_VOLUME, "Collie_volume_half_off"); - while (0 < collie_volume) { - if (collie_volume <= VOL_THRES) { - volume = 0; - } else { - if (collie_volume > delta) { - volume = collie_volume - delta; - } else { - volume = 0; - } - if (volume && volume < VOL_THRES) { - volume = VOL_THRES; - } - delta <<= 1; - } - m62332_senddata(0xff * volume / 100, M62332_EVR_CH); - collie_volume = volume; - udelay(100); - } - LEAVE(TRACE_VOLUME, "Collie_volume_half_off"); -} - -static void Collie_OP_SHDN_on(void) -{ -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_OP_SHDN,"Collie_OP_SHDN_on"); - if (!collie_op_shdn_on) { - /* set volume */ - Collie_volume_off(); - - /* OP_SHDN to GPIO 17 */ - /* alternate functions for the GPIOs */ - GAFR &= ~( COLLIE_GPIO_OPSHDN ); - - /* Set the direction: 17 output */ - GPDR |= ( COLLIE_GPIO_OPSHDN ); - - /* Set pin level (high) */ - GPSR |= ( COLLIE_GPIO_OPSHDN ); - - /* set volume */ - Collie_volume_on(); - - collie_op_shdn_on = 1; - } - LEAVE(TRACE_OP_SHDN,"Collie_OP_SHDN_on"); -#endif /* CONFIG_COLLIE_TS || CONFIG_COLLIE_TR0 */ -} - -static void Collie_OP_SHDN_off(void) -{ -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_OP_SHDN,"Collie_OP_SHDN_off"); - /* OP_SHDN to GPIO 17 */ - /* alternate functions for the GPIOs */ - GAFR &= ~( COLLIE_GPIO_OPSHDN ); - - /* Set the direction: 17 output */ - GPDR |= ( COLLIE_GPIO_OPSHDN ); - - /* Clear pin level (low) */ - GPCR |= ( COLLIE_GPIO_OPSHDN ); - - collie_op_shdn_on = 0; - LEAVE(TRACE_OP_SHDN,"Collie_OP_SHDN_off"); -#endif /* CONFIG_COLLIE_TS || CONFIG_COLLIE_TR0 */ + GPSR = ( COLLIE_GPIO_MIC ); } static inline void Collie_ssp_init(void) { - ENTER(TRACE_SSP, "Collie_ssp_init"); /* alternate functions for the GPIOs */ /* SSP port to GPIO 10,12,13, 19 */ GAFR |= ( GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SSP_CLK ); -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) - /* SSP port to GPIO 11 */ - GAFR |= GPIO_SSP_RXD; -#endif /* CONFIG_COLLIE_TS || CONFIG_COLLIE_TR0 */ /* Set the direction: 10, 12, 13 output; 19 input */ GPDR |= ( GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM ); GPDR &= ~( GPIO_SSP_CLK ); -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) - /* Set the direction: 11 input */ - GPDR &= ~( GPIO_SSP_RXD ); -#endif /* CONFIG_COLLIE_TS || CONFIG_COLLIE_TR0 */ /* enable SSP pin swap */ PPAR |= PPAR_SPR; @@ -1516,400 +666,162 @@ /* the SSP setting */ Ser4SSCR0 = (SSCR0_DataSize(16) | SSCR0_TI | SSCR0_SerClkDiv(2)); Ser4SSCR1 = (SSCR1_SClkIactL | SSCR1_SClk1P | SSCR1_ExtClk); - - LEAVE(TRACE_SSP, "Collie_ssp_init"); } static inline void Collie_ssp_on(void) { - ENTER(TRACE_SSP, "Collie_ssp_on"); /* turn on the SSP */ Ser4SSCR0 |= ( SSCR0_SSE ); - LEAVE(TRACE_SSP, "Collie_ssp_on"); } static inline void Collie_ssp_off(void) { - ENTER(TRACE_SSP, "Collie_ssp_off"); /* turn off the SSP */ Ser4SSCR0 &= ~( SSCR0_SSE ); - LEAVE(TRACE_SSP, "Collie_ssp_off"); -} - -static inline void Collie_sound_hard_init(void) -{ - ENTER(TRACE_ON, "Collie_sound_hard_init"); - Collie_hard_mute_init(); - Collie_audio_clock_init(); - Collie_paif_init(); - Collie_volume_init(); - Collie_ssp_init(); - Collie_MIC_init(); - - Collie_FS8KLPF_start(); - LEAVE(TRACE_ON, "Collie_sound_hard_init"); -} - -static inline void Collie_sound_hard_term(void) -{ - ENTER(TRACE_ON, "Collie_sound_hard_term"); -#ifdef DAC_OFF_WITH_DEVICE_OFF - /* DAC Off */ - Collie_DAC_off(); -#endif - LEAVE(TRACE_ON, "Collie_sound_hard_term"); -} - -static void Collie_FS8KLPF_start(void) -{ -#if defined(CONFIG_COLLIE_TS) || defined(CONFIG_COLLIE_TR0) - ENTER(TRACE_ON,"Collie_FS8KLPF_start"); - /* Set up TC35143 GPIO I/O Direction (GPIO5 output mode) */ - ucb1200_set_io_direction(TC35143_GPIO_FS8KLPF, - TC35143_IODIR_OUTPUT); - /* Set up TC35143 GPIO 5 (set LOW) */ - ucb1200_set_io(TC35143_GPIO_FS8KLPF, TC35143_IODAT_LOW); - LEAVE(TRACE_ON,"Collie_FS8KLPF_start"); -#endif /* CONFIG_COLLIE_TS || CONFIG_COLLIE_TR0 */ -} - -#ifdef CONFIG_PM -#if 0 -static void Collie_FS8KLPF_stop(void) -{ - /* Set up TC35143 GPIO I/O Direction (GPIO5 output mode) */ - ucb1200_set_io_direction(TC35143_GPIO_FS8KLPF, - TC35143_IODIR_OUTPUT); - /* Set up TC35143 GPIO 5 (set LOW) */ - ucb1200_set_io(TC35143_GPIO_FS8KLPF, TC35143_IODAT_HIGH); -} - -static void Collie_clock_stop(void) -{ - /* LoCoMo PCM audio interface */ - Collie_paif_off(); - - /* LoCoMo audio clock off */ - Collie_audio_clock_off(); -} -#endif -#endif - -#ifdef TRY_DELAY_OFF /* H.Hayami SHARP 2001.12.19 */ -static unsigned long in_timehandle = 0; -static struct timer_list timer; - -static void collieDoDelayedSilence(void) -{ - ENTER(TRACE_ON,"collieDoDelayedSilence"); - down(&df_sem); - if(isDelayed(DELAY_HARD_MUTE_ON)) { - Collie_hard_mute_on(); - } - if(isDelayed(DELAY_DAC_OFF)) { - Collie_DAC_off(); - } - ResetDelayAll(); - up(&df_sem); - LEAVE(TRACE_ON,"colliDoDelayedSilence"); -} - -static void collieDelayedSilence(void) -{ - ENTER(TRACE_ON,"collieDelayedSilence"); - while (1) { - sleep_on(&delay_off); - collieDoDelayedSilence(); - } - LEAVE(TRACE_ON,"collieDelayedSilence"); -} - -static void collieStartDelayedSilence(unsigned long data) -{ - ENTER(TRACE_ON,"collieStartDelayedSilence"); - in_timehandle = 0; - wake_up(&delay_off); - LEAVE(TRACE_ON,"collieStartDelayedSilence"); -} - -static void collieTriggerDelayedSilence(void) -{ - ENTER(TRACE_ON,"collieTriggerDelayedSilence"); - in_timehandle = 1; - init_timer(&timer); - timer.function = collieStartDelayedSilence; - timer.expires = jiffies + 5*100; - add_timer(&timer); - LEAVE(TRACE_ON,"collieTriggerDelayedSilence"); -} - -static void collieCancelDelayedSilence(void) -{ - ENTER(TRACE_ON,"collieCancelDelayedSilence"); - down(&df_sem); - ResetDelayAll();; - up(&df_sem); - if (in_timehandle) { - del_timer(&timer); - in_timehandle = 0; - } - LEAVE(TRACE_ON,"collieCancelDelayedSilence"); -} -#endif - -static void Collie_disable_sound(void) -{ - ENTER(TRACE_ON,"Collie_disable_sound"); - sa1100_dma_stop(COLLIE_SOUND_DMA_CHANNEL); - sa1100_dma_flush_all(COLLIE_SOUND_DMA_CHANNEL); -#ifndef TRY_DELAY_OFF /* H.Hayami SHARP 2001.12.18 */ - Collie_volume_half_off(); - Collie_hard_mute_on(); - Collie_soft_mute_on(); - - Collie_ssp_off(); - - /* Collie_clock_stop(); */ -#endif - LEAVE(TRACE_ON,"Collie_disable_sound"); -} - -static void CollieSilence(void) -{ - ENTER(TRACE_ON,"CollieSilence"); - /* Disable sound & DMA */ - Collie_disable_sound(); - -#ifdef TRY_DELAY_OFF /* H.Hayami SHARP 2001.12.18 */ - Collie_volume_half_off(); - Collie_hard_mute_delay_on(); - Collie_soft_mute_on(); - - Collie_ssp_off(); - - /* Collie_clock_stop(); */ -#endif - -#if 0 /* H.Hayami SHARP 2001.12.18 */ -#if !defined(CONFIG_COLLIE_TS) && !defined(CONFIG_COLLIE_TR0) && \ - !defined(CONFIG_COLLIE_TR1) && !defined(CONFIG_COLLIE_DEV) - Collie_volume_off(); -#endif -#endif - Collie_OP_SHDN_off(); - Collie_soft_DAC_off(); - Collie_paif_off(); - Collie_audio_clock_off(); - - //Collie_MIC_on(); - -#ifndef DAC_OFF_WITH_DEVICE_OFF - /* DAC Off */ -#ifdef TRY_DELAY_OFF /* H.Hayami 2001.12.15 */ - Collie_DAC_delay_off(); -#else - Collie_DAC_off(); -#endif -#endif /* end DAC_OFF_WITH_DEVICE_OFF */ - - /* AMP Off */ - Collie_AMP_off(); - -#ifdef TRY_DELAY_OFF /* H.Hayami SHARP 2001.12.18 */ - collieTriggerDelayedSilence(); -#endif - LEAVE(TRACE_ON,"CollieSilence"); -} - -static int CollieGetSamp(void) -{ - ENTER(TRACE_ON,"CollieGetSamp"); - switch (sound.soft.speed) { - case 8000: - LEAVE(TRACE_ON,"CollieGetSamp"); - return clock_set_data[7]; - case 44100: - LEAVE(TRACE_ON,"CollieGetSamp"); - return clock_set_data[0]; - case 22050: - LEAVE(TRACE_ON,"CollieGetSamp"); - return clock_set_data[1]; - case 11025: - LEAVE(TRACE_ON,"CollieGetSamp"); - return clock_set_data[2]; - case 48000: - LEAVE(TRACE_ON,"CollieGetSamp"); - return clock_set_data[3]; - case 32000: - LEAVE(TRACE_ON,"CollieGetSamp"); - return clock_set_data[4]; - case 24000: - LEAVE(TRACE_ON,"CollieGetSamp"); - return clock_set_data[5]; - case 16000: - LEAVE(TRACE_ON,"CollieGetSamp"); - return clock_set_data[6]; - default: - printk("Collie sound: Illegal sound rate %d\n", sound.soft.speed); - LEAVE(TRACE_ON,"CollieGetSamp"); - return clock_set_data[7]; - } -} - -static inline void Collie_DAC_sendbit(int bit_data) -{ - ENTER(TRACE_SENDDATA,"Collie_DAC_sendbit"); - if (bit_data & 1) { - LCM_GPO |= (LCM_GPIO_DAC_SDATA); - } else { - LCM_GPO &= ~(LCM_GPIO_DAC_SDATA); - } - - udelay(1); - LCM_GPO |= (LCM_GPIO_DAC_SCK); - - udelay(1); - LCM_GPO &= ~(LCM_GPIO_DAC_SCK); - udelay(1); - LCM_GPO &= ~(LCM_GPIO_DAC_SDATA); - udelay(1); - LEAVE(TRACE_SENDDATA,"Collie_DAC_sendbit"); -} - -static void Collie_DAC_sendword(int data) -{ - int i; - - ENTER(TRACE_SENDDATA,"Collie_DAC_sendword"); -#if defined(CONFIG_COLLIE_PCM1741) - - LCM_GPO &= ~(LCM_GPIO_DAC_SCK); - udelay(1); - LCM_GPO |= (LCM_GPIO_DAC_SLOAD); - udelay(1); - - for (i = 0; i < 16; i++) - Collie_DAC_sendbit(data >> (15 - i)); - - LCM_GPO &= ~(LCM_GPIO_DAC_SLOAD); - udelay(2); - -#elif defined(CONFIG_COLLIE_PCM1717) - - LCM_GPO &= ~(LCM_GPIO_DAC_SLOAD); - udelay(1000); - LCM_GPO |= (LCM_GPIO_DAC_SLOAD); - udelay(1000); - LCM_GPO &= ~(LCM_GPIO_DAC_SCK); - udelay(1000); - - for (i = 0; i < 16; i++) - Collie_DAC_sendbit(data >> (15 - i)); - - LCM_GPO &= ~(LCM_GPIO_DAC_SLOAD); - udelay(1000); - LCM_GPO |= (LCM_GPIO_DAC_SLOAD); - udelay(1000); - LCM_GPO &= ~(LCM_GPIO_DAC_SLOAD); - udelay(1000); - -#endif - LEAVE(TRACE_SENDDATA,"Collie_DAC_sendword"); } -void -Collie_audio_power_on(void) + +static inline void Collie_sound_hard_init(void) { - int send_data; + Collie_hard_mute_init(); + Collie_audio_clock_init(); + Collie_paif_off(); + Collie_volume_init(); + Collie_ssp_init(); + Collie_MIC_init(); + Collie_soft_mute_on(); + Collie_DAC_on(); +} - ENTER(TRACE_ON,"Collie_audio_power_on"); +void Collie_recording_on(void) +{ + collie_recording=1; + if (!playing) + Collie_DAC_on(); + else + Collie_hard_mute_left_on(); + Collie_MIC_on(); +} -#ifdef TRY_DELAY_OFF /* H.Hayami SHARP 2001.12.19 */ - collieCancelDelayedSilence(); -#endif +void Collie_recording_off(void) +{ + collie_recording=0; + Collie_MIC_off(); + if (!playing) + Collie_DAC_off(); + else + Collie_hard_mute_left_off(); +} +static void Collie_audio_power_on(void) +{ + playing=1; collie_amp_init = 0; - - /* OP_SHDN off */ - Collie_OP_SHDN_off(); - - /* AMP on */ - Collie_AMP_on(); - - /* DAC ON */ - Collie_DAC_on(); - - Collie_MIC_off(); - Collie_ssp_on(); - - /* LoCoMo Audio clock */ - Collie_audio_clock_off(); + if (!collie_recording) + Collie_DAC_on(); + Collie_ssp_on(); + Collie_audio_clock_off(); /* LoCoMo Audio clock */ Collie_audio_clock_on(); - - /* LoCoMo PCM audio interface */ - Collie_paif_on(); - + Collie_paif_on(); /* LoCoMo PCM audio interface */ udelay(1000); - - /* DAC Setting */ Collie_DAC_init(); - Collie_soft_DAC_on(); - Collie_soft_mute_init(); + Collie_soft_mute_off(); + Collie_hard_mute_off(); + if (collie_recording) + Collie_hard_mute_left_on(); + Collie_volume_set(sound.volume); +} - sound.hard = sound.soft; +static void Collie_audio_power_off(void){ /* Disable sound only */ + Collie_volume_set(0); + Collie_hard_mute_on(); + Collie_soft_mute_on(); + Collie_ssp_off(); + Collie_soft_DAC_off(); + Collie_paif_off(); + Collie_audio_clock_off(); + if (!collie_recording) + Collie_DAC_off(); + playing=0; +} -#if !defined(CONFIG_COLLIE_TS) && !defined(CONFIG_COLLIE_TR0) && \ - !defined(CONFIG_COLLIE_TR1) && !defined(CONFIG_COLLIE_DEV) - /* Volume set */ - Collie_volume_half_adjust(); - { - int i; - for (i=0; i<10*1000; i++) { - udelay(1); + +static inline void Collie_volume_init(void) +{ + m62332_senddata(0, M62332_EVR_CH); + collie_volume = 0; +} + +#define VOL_THRES 10 + +static void Collie_volume_set(int dest) +{ + int chn; + while (dest != collie_volume) { + chn = dest-collie_volume; + if (chn>VOL_THRES) + chn=VOL_THRES; + else if (chn<-VOL_THRES) + chn=-VOL_THRES; + if (chn) { + collie_volume += chn; + m62332_senddata(0xff * collie_volume / 100, M62332_EVR_CH); } + udelay(100); } -#endif +} - Collie_soft_mute_off(); - Collie_hard_mute_off(); +static int sound_set_speed(int speed) +{ + if (speed < 0) { + return(sound.speed); + } + + if (speed<8000) sound.speed=8000; + else if (speed<=11025) sound.speed=11025; + else if (speed<=16000) sound.speed=16000; + else if (speed<=22050) sound.speed=22050; + else if (speed<=24000) sound.speed=24000; + else if (speed<=32000) sound.speed=32000; + else if (speed<=44100) sound.speed=44100; + else sound.speed=48000; + + /* LoCoMo Audio clock */ + Collie_audio_clock_off(); + Collie_audio_clock_on(); + return(sound.speed); +} - LEAVE(TRACE_ON,"Collie_audio_power_on"); +/*** Mid level stuff *********************************************************/ + +static void Collie_Set_Volume(int volume) +{ + sound.volume = volume & 0xff; + sound.volume += ( volume & 0xff00 >> 8); + sound.volume >>=1; + if (sound.volume>100) sound.volume=100; } -static void CollieInit(void) +static int Collie_Get_Volume(void) { - ENTER(TRACE_ON,"CollieInit"); - sound.hard = sound.soft; - LEAVE(TRACE_ON,"CollieInit"); + return ( sound.volume << 8 | sound.volume ); } + static void Collie_sq_interrupt(void* id, int size) { audio_buf_t *b = (audio_buf_t *) id; - ENTER(TRACE_INTERRUPT,"Collie_sq_interrupt"); -/***** DEBUG ***** -printk("Collie_sq_interrupt: Start\n"); -*****************/ + /* * Current buffer is sent: wake up any process waiting for it. */ - ENTER(TRACE_SEM,"up sem"); up(&b->sem); - LEAVE(TRACE_SEM,"up sem"); -/***** DEBUG ***** -printk("Collie_sq_interrupt: up End\n"); -*****************/ /* And any process polling on write. */ - ENTER(TRACE_SEM,"up wait"); - wake_up(&b->sem.wait); - LEAVE(TRACE_SEM,"up wait"); -/***** DEBUG ***** -printk("Collie_sq_interrupt: wake_up End\n"); -*****************/ + wake_up_interruptible(&b->sem.wait); + /* And indicate which was the last buffer sent */ DPRINTK("Collie_sq_interrupt \n"); - LEAVE(TRACE_INTERRUPT,"Collie_sq_interrupt"); } @@ -1917,191 +829,52 @@ { int err; - ENTER(TRACE_ON,"CollieIrqInit"); err = sa1100_request_dma(&collie_dmasound_irq, "dmasound", DMA_Ser4SSPWr); if (err) { - LEAVE(TRACE_ON,"CollieIrqInit"); return 0; } - /* printk("collie_dmasound_irq=%d\n", collie_dmasound_irq); */ + printk("collie_dmasound_irq=%d\n", collie_dmasound_irq); sa1100_dma_set_callback(collie_dmasound_irq, (dma_callback_t)Collie_sq_interrupt); - - /* Disable sound & DMA */ - Collie_disable_sound(); - - LEAVE(TRACE_ON,"CollieIrqInit"); + sa1100_dma_stop(COLLIE_SOUND_DMA_CHANNEL); + sa1100_dma_flush_all(COLLIE_SOUND_DMA_CHANNEL); + Collie_audio_power_off(); return(1); - -} - -#ifdef MODULE -static void CollieIrqCleanUp(void) -{ - ENTER(TRACE_ON,"CollieIrqCleanUp"); - /* Disable sound & DMA */ - Collie_disable_sound(); - - /* release the interrupt */ - free_irq(IRQ_DMA, Collie_sq_interrupt); - LEAVE(TRACE_ON,"CollieIrqCleanUp"); } -#endif /* MODULE */ - static int CollieSetFormat(int format) { int size; - ENTER(TRACE_ON,"CollieSetFormat"); - /* Falcon sound DMA supports 8bit and 16bit modes */ - switch (format) { case AFMT_QUERY: - LEAVE(TRACE_ON,"CollieSetFormat"); - return(sound.soft.format); - case AFMT_MU_LAW: - size = 8; - ct_func = sound.trans->ct_ulaw; - break; - case AFMT_A_LAW: - size = 8; - ct_func = sound.trans->ct_alaw; - break; - case AFMT_S8: - size = 8; - ct_func = sound.trans->ct_s8; - break; - case AFMT_U8: - size = 8; - ct_func = sound.trans->ct_u8; - break; - case AFMT_S16_BE: - size = 16; - ct_func = sound.trans->ct_s16be; - break; - case AFMT_U16_BE: - size = 16; - ct_func = sound.trans->ct_u16be; - break; - case AFMT_S16_LE: - size = 16; - ct_func = sound.trans->ct_s16le; - break; - case AFMT_U16_LE: + return(sound.format); + default: /* This is the only one supported by the hardware it seems */ size = 16; - ct_func = sound.trans->ct_u16le; - break; - default: /* :-) */ - size = 8; - format = AFMT_S8; - } - - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) { - sound.dsp.format = format; - sound.dsp.size = sound.soft.size; + format = AFMT_S16_LE; } + sound.format = format; + sound.size = size; - LEAVE(TRACE_ON,"CollieSetFormat"); return(format); } -/*** Machine definitions *****************************************************/ - -static MACHINE machCollie = { - DMASND_COLLIE, // int type - NULL, // void *dma_alloc(uint, int) - NULL, // void dma_free(void *, uint) - CollieIrqInit, // void irqinit(void) -#ifdef MODULE - CollieIrqCleanUp, // void irqcleanup(void) -#endif /* MODULE */ - CollieInit, // void init(void) - CollieSilence, // void silence(void) - CollieSetFormat, // int setFormat(int) - NULL, // int setVolume(int) - NULL, // int setBass(int) - NULL, // int setTreble(int) - NULL, // int setGain(int) - NULL // void play(void) -}; - - -/*** Mid level stuff *********************************************************/ - - -static void sound_silence(void) -{ - ENTER(TRACE_ON,"sound_silence"); - /* update hardware settings one more */ - //(*sound.mach.init)(); - (*sound.mach.silence)(); - LEAVE(TRACE_ON,"sound_silence"); - -} - - -static void sound_init(void) -{ - ENTER(TRACE_ON,"sound_init"); - (*sound.mach.init)(); - LEAVE(TRACE_ON,"sound_init"); -} - - -static int sound_set_format(int format) -{ - ENTER(TRACE_ON,"sound_set_format"); - LEAVE(TRACE_ON,"sound_set_format"); - return(*sound.mach.setFormat)(format); -} - - -static int sound_set_speed(int speed) -{ - ENTER(TRACE_ON,"sound_set_speed"); - if (speed < 0) { - LEAVE(TRACE_ON,"sound_set_speed"); - return(sound.soft.speed); - } - - sound.soft.speed = speed; - (*sound.mach.init)(); - if (sound.minDev == SND_DEV_DSP) - sound.dsp.speed = sound.soft.speed; - - /* LoCoMo Audio clock */ - Collie_audio_clock_off(); - Collie_audio_clock_on(); - - LEAVE(TRACE_ON,"sound_set_speed"); - return(sound.soft.speed); -} static int sound_set_stereo(int stereo) { - ENTER(TRACE_ON,"sound_set_stereo"); +/* Only stereo is supported by hardware */ if (stereo < 0) { - LEAVE(TRACE_ON,"sound_set_stereo"); - return(sound.soft.stereo); + return(sound.stereo); } + return(1); +} - stereo = !!stereo; /* should be 0 or 1 now */ - - sound.soft.stereo = stereo; - if (sound.minDev == SND_DEV_DSP) - sound.dsp.stereo = stereo; - //(*sound.mach.init)(); - LEAVE(TRACE_ON,"sound_set_stereo"); - return(stereo); -} +/* Higher level stuff ************************************************/ /* * /dev/mixer abstraction @@ -2109,20 +882,15 @@ static int mixer_open(struct inode *inode, struct file *file) { - ENTER(TRACE_ON,"mixer_open"); MOD_INC_USE_COUNT; mixer.busy = 1; - LEAVE(TRACE_ON,"mixer_open"); return 0; } - static int mixer_release(struct inode *inode, struct file *file) { - ENTER(TRACE_ON,"mixer_release"); mixer.busy = 0; MOD_DEC_USE_COUNT; - LEAVE(TRACE_ON,"mixer_release"); return 0; } @@ -2132,58 +900,37 @@ { int data; - ENTER(TRACE_ON,"mixer_ioctl"); - switch (sound.mach.type) { - case DMASND_COLLIE: - { - switch (cmd) { - case SOUND_MIXER_READ_DEVMASK: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, SOUND_MASK_VOLUME ); - case SOUND_MIXER_READ_RECMASK: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_STEREODEVS: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, SOUND_MASK_VOLUME); - case SOUND_MIXER_READ_CAPS: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, 0); - - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - Collie_Set_Volume(data); - case SOUND_MIXER_READ_VOLUME: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, Collie_Get_Volume()); - - case SOUND_MIXER_READ_TREBLE: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_WRITE_TREBLE: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, 0); - - case SOUND_MIXER_WRITE_MIC: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_MIC: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, 0); - - case SOUND_MIXER_READ_SPEAKER: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_WRITE_SPEAKER: - LEAVE(TRACE_ON,"mixer_ioctl"); - return IOCTL_OUT(arg, 0); - } - break; - } - } - LEAVE(TRACE_ON,"mixer_ioctl"); + switch (cmd) { + case SOUND_MIXER_READ_DEVMASK: + return IOCTL_OUT(arg, headphone ? SOUND_MASK_VOLUME : 0 ); + case SOUND_MIXER_READ_RECMASK: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_READ_STEREODEVS: + return IOCTL_OUT(arg, headphone ? SOUND_MASK_VOLUME : 0 ); + case SOUND_MIXER_READ_CAPS: + return IOCTL_OUT(arg, 0); + + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + Collie_Set_Volume(data); + case SOUND_MIXER_READ_VOLUME: + return IOCTL_OUT(arg, Collie_Get_Volume()); + case SOUND_MIXER_READ_TREBLE: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_WRITE_TREBLE: + return IOCTL_OUT(arg, 0); + + case SOUND_MIXER_WRITE_MIC: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_READ_MIC: + return IOCTL_OUT(arg, 0); + + case SOUND_MIXER_READ_SPEAKER: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_WRITE_SPEAKER: + return IOCTL_OUT(arg, 0); + } return -EINVAL; - } @@ -2198,32 +945,13 @@ static void __init mixer_init(void) { -#ifndef MODULE - int mixer_unit; -#endif - ENTER(TRACE_ON,"mixer_init"); mixer_unit = register_sound_mixer(&mixer_fops, -1); if (mixer_unit < 0) { - LEAVE(TRACE_ON,"mixer_init"); return; } - mixer.busy = 0; - sound.treble = 0; - sound.bass = 0; - switch (sound.mach.type) { - case DMASND_COLLIE: - // sound.volume_left = 0x3c; - // sound.volume_right = 0x3c; - sound.volume_left = 80; - sound.volume_right = 80; - collie_main_volume = sound.volume_left; - break; - } - - // printk("mixer_init : ret \n"); - - LEAVE(TRACE_ON,"mixer_init"); + sound.volume = 80; + Collie_volume_set(sound.volume); } /* This function allocates the buffer structure array and buffer data space @@ -2237,11 +965,9 @@ char *dmabuf = 0; dma_addr_t dmaphys = 0; - ENTER(TRACE_ON,"sq_allocate_buffers"); DPRINTK("sq_allocate_buffers\n"); if (s->buffers) { - LEAVE(TRACE_ON,"sq_allocate_buffers"); return -EBUSY; } @@ -2279,10 +1005,8 @@ b->start = dmabuf; b->dma_addr = dmaphys; + b->idx = frag; sema_init(&b->sem, 1); - DPRINTK("buf %d: start %p dma %p\n", frag, b->start, - b->dma_addr); - dmabuf += s->fragsize; dmaphys += s->fragsize; dmasize -= s->fragsize; @@ -2291,13 +1015,12 @@ s->buf_idx = 0; s->buf = &s->buffers[0]; - LEAVE(TRACE_ON,"sq_allocate_buffers"); + return 0; err: printk("sound driver : unable to allocate audio memory\n "); sq_release_buffers(s); - LEAVE(TRACE_ON,"sq_allocate_buffers"); return -ENOMEM; } @@ -2307,7 +1030,6 @@ static void sq_release_buffers(audio_stream_t * s) { - ENTER(TRACE_ON,"sq_release_buffers"); DPRINTK("sq_release_buffers\n"); /* ensure DMA won't run anymore */ @@ -2328,7 +1050,6 @@ s->buf_idx = 0; s->buf = NULL; - LEAVE(TRACE_ON,"sq_release_buffers"); } static ssize_t sq_write(struct file *file, const char *src, size_t uLeft, @@ -2339,27 +1060,20 @@ u_char *dest; ssize_t uUsed, bUsed, bLeft, ret = 0; - ENTER(TRACE_WRITE,"sq_write"); DPRINTK("sq_write: uLeft=%d\n", uLeft); - /* OP_SHDN on */ - Collie_OP_SHDN_on(); - switch (file->f_flags & O_ACCMODE) { case O_WRONLY: case O_RDWR: break; default: - LEAVE(TRACE_WRITE,"sq_write1"); return -EPERM; } if (!s->buffers && sq_allocate_buffers(s)) { - LEAVE(TRACE_WRITE,"sq_write2"); return -ENOMEM; } -#if 1 if (collie_resume == 1) { int i; collie_resume = 0; @@ -2367,10 +1081,9 @@ udelay(1); } } -#endif #ifdef CONFIG_PM /* Auto Power off cancel */ - autoPowerCancel = 0; +// autoPowerCancel = 0; #endif while (uLeft > 0) { @@ -2379,41 +1092,30 @@ /* Wait for a buffer to become free */ if (file->f_flags & O_NONBLOCK) { ret = -EAGAIN; - ENTER(TRACE_SEM,"down_try sem"); if (down_trylock(&b->sem)) { - LEAVE(TRACE_SEM,"down_try1 sem"); break; } - LEAVE(TRACE_SEM,"down_try2 sem"); } else { ret = -ERESTARTSYS; - ENTER(TRACE_SEM,"down_int sem"); - //printk("### 0x%08x:%d\n", &b->sem.count, atomic_read(&b->sem.count)); if (down_interruptible(&b->sem)) { - LEAVE(TRACE_SEM,"down_int1 sem"); break; } - LEAVE(TRACE_SEM,"down_int2 sem"); } dest = b->start + b->size; bUsed = 0; bLeft = s->fragsize - b->size; - if (ct_func) { - uUsed = ct_func(src, uLeft, dest, &bUsed, bLeft); + if (collie_ct_s16) { + uUsed = collie_ct_s16(src, uLeft, dest, &bUsed, bLeft); cpu_cache_clean_invalidate_range((unsigned long)dest, (unsigned long)(dest+(audio_fragsize)), 0); } else { - LEAVE(TRACE_WRITE,"sq_write3"); return -EFAULT; } if (uUsed < 0) { - ENTER(TRACE_SEM,"up sem"); up(&b->sem); - LEAVE(TRACE_SEM,"up sem"); - LEAVE(TRACE_WRITE,"sq_write4"); return -EFAULT; } src += uUsed; @@ -2421,9 +1123,7 @@ b->size += bUsed; if (b->size < s->fragsize) { - ENTER(TRACE_SEM,"up sem"); up(&b->sem); - LEAVE(TRACE_SEM,"up sem"); break; } @@ -2431,7 +1131,7 @@ sa1100_dma_queue_buffer(COLLIE_SOUND_DMA_CHANNEL, (void *) b, b->dma_addr, b->size); - Collie_volume_half_adjust(); + Collie_volume_set(sound.volume); b->size = 0; /* indicate that the buffer has been sent */ NEXT_BUF(s, buf); @@ -2440,7 +1140,6 @@ if ((src - buffer0)) ret = src - buffer0; DPRINTK("sq_write: return=%d\n", ret); - LEAVE(TRACE_WRITE,"sq_write0"); return ret; } @@ -2450,7 +1149,6 @@ unsigned int mask = 0; int i; - ENTER(TRACE_ON,"sq_poll"); DPRINTK("sq_poll(): mode=%s%s\n", (file->f_mode & FMODE_READ) ? "r" : "", (file->f_mode & FMODE_WRITE) ? "w" : ""); @@ -2458,12 +1156,9 @@ if (file->f_mode & FMODE_WRITE) { if (!output_stream.buffers && sq_allocate_buffers(&output_stream)) { - LEAVE(TRACE_ON,"sq_poll"); return -ENOMEM; } - ENTER(TRACE_SEM,"poll_wait wait"); poll_wait(file, &output_stream.buf->sem.wait, wait); - LEAVE(TRACE_SEM,"poll_wait wait"); } if (file->f_mode & FMODE_WRITE) { @@ -2477,65 +1172,33 @@ (mask & POLLIN) ? "r" : "", (mask & POLLOUT) ? "w" : ""); - LEAVE(TRACE_ON,"sq_poll"); return mask; } static int sq_open(struct inode *inode, struct file *file) { - ENTER(TRACE_ON,"sq_open"); DPRINTK("sq_open\n"); if (((file->f_flags & O_ACCMODE) == O_WRONLY) || ((file->f_flags & O_ACCMODE) == O_RDWR)) { -#if 0 - MOD_INC_USE_COUNT; - while(audio_wr_refcount) { - SLEEP(open_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) { - MOD_DEC_USE_COUNT; - LEAVE(TRACE_ON,"sq_open"); - return -EINTR; - } - } -#else if (audio_wr_refcount) { DPRINTK(" sq_open EBUSY\n"); - LEAVE(TRACE_ON,"sq_open"); return -EBUSY; } MOD_INC_USE_COUNT; -#endif audio_wr_refcount++; } else { DPRINTK(" sq_open EINVAL\n"); - LEAVE(TRACE_ON,"sq_open"); return -EINVAL; } - if (audio_wr_refcount == 1) { - DPRINTK("cold\n"); - - audio_fragsize = AUDIO_FRAGSIZE_DEFAULT; - audio_nbfrags = AUDIO_NBFRAGS_DEFAULT; - sq_release_buffers(&output_stream); - sound.minDev = MINOR(inode->i_rdev) & 0x0f; - sound.soft = sound.dsp; - sound.hard = sound.dsp; - - if ((MINOR(inode->i_rdev) & 0x0f) == SND_DEV_AUDIO) { - sound_set_speed(8000); - sound_set_stereo(0); - sound_set_format(AFMT_MU_LAW); - } - Collie_audio_power_on(); - } -#if 0 - MOD_INC_USE_COUNT; -#endif - LEAVE(TRACE_ON,"sq_open"); - return 0; + audio_fragsize = AUDIO_FRAGSIZE_DEFAULT; + audio_nbfrags = AUDIO_NBFRAGS_DEFAULT; + sq_release_buffers(&output_stream); + output_stream.buf_idx=0; + Collie_audio_power_on(); + return 0; } static int sq_fsync(struct file *filp, struct dentry *dentry) @@ -2543,11 +1206,9 @@ audio_stream_t *s = &output_stream; audio_buf_t *b = s->buf; - ENTER(TRACE_ON,"sq_fsync"); DPRINTK("sq_fsync\n"); if (!s->buffers) { - LEAVE(TRACE_ON,"sq_fsync"); return 0; } @@ -2557,12 +1218,10 @@ #ifdef CONFIG_PM /* Auto Power off cancel */ - autoPowerCancel = 0; +// autoPowerCancel = 0; #endif - ENTER(TRACE_SEM,"down sem"); down(&b->sem); - LEAVE(TRACE_SEM,"down sem"); sa1100_dma_queue_buffer(COLLIE_SOUND_DMA_CHANNEL, (void *) b, b->dma_addr, b->size); b->size = 0; @@ -2576,23 +1235,15 @@ * - the buffer was already free thus nothing else to sync. */ b = s->buffers + ((s->nbfrags + s->buf_idx - 1) % s->nbfrags); - ENTER(TRACE_SEM,"down-int sem"); if (down_interruptible(&b->sem)) { - LEAVE(TRACE_SEM,"down-int sem"); - LEAVE(TRACE_ON,"sq_fsync"); return -EINTR; } - LEAVE(TRACE_SEM,"down-int sem"); - ENTER(TRACE_SEM,"up sem"); up(&b->sem); - LEAVE(TRACE_SEM,"up sem"); - LEAVE(TRACE_ON,"sq_fsync"); return 0; } static int sq_release(struct inode *inode, struct file *file) { - ENTER(TRACE_ON,"sq_release"); DPRINTK("sq_release\n"); switch (file->f_flags & O_ACCMODE) { @@ -2606,24 +1257,12 @@ } if (!audio_wr_refcount) { - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_silence(); - Collie_OP_SHDN_off(); + sa1100_dma_stop(COLLIE_SOUND_DMA_CHANNEL); + sa1100_dma_flush_all(COLLIE_SOUND_DMA_CHANNEL); + Collie_audio_power_off(); } -#if 0 - switch (file->f_flags & O_ACCMODE) { - case O_WRONLY: - case O_RDWR: - if (!audio_wr_refcount) { - WAKE_UP(open_queue); - } - } -#endif - MOD_DEC_USE_COUNT; - LEAVE(TRACE_ON,"sq_release"); return 0; } @@ -2634,8 +1273,8 @@ u_long fmt; int data; long val; +// audio_buf_info abinfo; - ENTER(TRACE_ON,"sq_ioctl"); switch (cmd) { case SNDCTL_DSP_RESET: switch (file->f_flags & O_ACCMODE) { @@ -2643,11 +1282,9 @@ case O_RDWR: sq_release_buffers(&output_stream); } - LEAVE(TRACE_ON,"sq_ioctl"); return 0; case SNDCTL_DSP_POST: case SNDCTL_DSP_SYNC: - LEAVE(TRACE_ON,"sq_ioctl"); return sq_fsync(file, file->f_dentry); /* ++TeSche: before changing any of these it's @@ -2656,59 +1293,34 @@ case SNDCTL_DSP_SPEED: sq_fsync(file, file->f_dentry); IOCTL_IN(arg, data); - LEAVE(TRACE_ON,"sq_ioctl"); return IOCTL_OUT(arg, sound_set_speed(data)); case SNDCTL_DSP_STEREO: sq_fsync(file, file->f_dentry); IOCTL_IN(arg, data); - LEAVE(TRACE_ON,"sq_ioctl"); return IOCTL_OUT(arg, sound_set_stereo(data)); - case SOUND_PCM_WRITE_CHANNELS: + case SNDCTL_DSP_CHANNELS: sq_fsync(file, file->f_dentry); IOCTL_IN(arg, data); - LEAVE(TRACE_ON,"sq_ioctl"); return IOCTL_OUT(arg, sound_set_stereo(data-1)+1); case SNDCTL_DSP_SETFMT: sq_fsync(file, file->f_dentry); IOCTL_IN(arg, data); - LEAVE(TRACE_ON,"sq_ioctl"); - return IOCTL_OUT(arg, sound_set_format(data)); + return IOCTL_OUT(arg, CollieSetFormat(data)); case SNDCTL_DSP_GETFMTS: - fmt = 0; - if (sound.trans) { - if (sound.trans->ct_ulaw) - fmt |= AFMT_MU_LAW; - if (sound.trans->ct_alaw) - fmt |= AFMT_A_LAW; - if (sound.trans->ct_s8) - fmt |= AFMT_S8; - if (sound.trans->ct_u8) - fmt |= AFMT_U8; - if (sound.trans->ct_s16be) - fmt |= AFMT_S16_BE; - if (sound.trans->ct_u16be) - fmt |= AFMT_U16_BE; - if (sound.trans->ct_s16le) - fmt |= AFMT_S16_LE; - if (sound.trans->ct_u16le) - fmt |= AFMT_U16_LE; - } - LEAVE(TRACE_ON,"sq_ioctl"); + fmt = AFMT_S16_LE; return IOCTL_OUT(arg, fmt); case SNDCTL_DSP_GETBLKSIZE: - LEAVE(TRACE_ON,"sq_ioctl"); return IOCTL_OUT(arg, audio_fragsize); case SNDCTL_DSP_SUBDIVIDE: break; case SNDCTL_DSP_SETFRAGMENT: if (output_stream.buffers) { - LEAVE(TRACE_ON,"sq_ioctl"); return -EBUSY; } get_user(val, (long *) arg); audio_fragsize = 1 << (val & 0xFFFF); - if (audio_fragsize < 16) - audio_fragsize = 16; + if (audio_fragsize < 256) + audio_fragsize = 256; if (audio_fragsize > 16384) audio_fragsize = 16384; audio_nbfrags = (val >> 16) & 0x7FFF; @@ -2717,46 +1329,54 @@ if (audio_nbfrags * audio_fragsize > 128 * 1024) audio_nbfrags = 128 * 1024 / audio_fragsize; if (sq_allocate_buffers(&output_stream)) { - LEAVE(TRACE_ON,"sq_ioctl"); return -ENOMEM; } - LEAVE(TRACE_ON,"sq_ioctl"); return 0; -#if 1 // 2003.2.14 +/* case SNDCTL_DSP_GETOSPACE: + abinfo.fragsize = audio_fragsize; + abinfo.fragstotal = audio_nbfrags; + abinfo.fragments = lastsent-output_stream.buf_idx; + if (abinfo.fragments<0) + abinfo.fragments += abinfo.fragstotal; + abinfo.bytes = abinfo.fragments*abinfo.fragsize; + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; +*/ case SNDCTL_DSP_GETOSPACE: { - audio_buf_info inf = { 0, }; + audio_stream_t *s = &output_stream; + audio_buf_info *inf = (audio_buf_info *) arg; + int err = verify_area(VERIFY_WRITE, inf, sizeof(*inf)); int i; + int frags = 0, bytes = 0; - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - if (!output_stream.buffers && sq_allocate_buffers(&output_stream)) - return -ENOMEM; - for (i = 0; i < output_stream.nbfrags; i++) { - if (atomic_read(&output_stream.buffers[i].sem.count) > 0) { - if (output_stream.buffers[i].size == 0) - inf.fragments++; - inf.bytes += output_stream.fragsize - output_stream.buffers[i].size; - } + if (err) + return err; + if (output_stream.buffers) { + for (i = 0; i < s->nbfrags; i++) { + if (atomic_read(&s->buffers[i].sem.count) > 0) { + if (s->buffers[i].size == 0) frags++; + bytes += s->fragsize - s->buffers[i].size; + } + } + put_user(s->nbfrags, &inf->fragstotal); + put_user(s->fragsize, &inf->fragsize); + } else { + frags=audio_nbfrags; + bytes=frags*audio_fragsize; + put_user(frags, &inf->fragstotal); + put_user(audio_fragsize, &inf->fragsize); } - inf.fragstotal = output_stream.nbfrags; - inf.fragsize = output_stream.fragsize; - return copy_to_user((void *)arg, &inf, sizeof(inf)); + put_user(frags, &inf->fragments); + return put_user(bytes, &inf->bytes); } -#endif - default: - LEAVE(TRACE_ON,"sq_ioctl"); return mixer_ioctl(inode, file, cmd, arg); } - LEAVE(TRACE_ON,"sq_ioctl"); return -EINVAL; } - - static struct file_operations sq_fops = { llseek: sound_lseek, @@ -2770,40 +1390,18 @@ static void __init sq_init(void) { -#ifndef MODULE - int sq_unit; -#endif - ENTER(TRACE_ON,"sq_init"); sq_unit = register_sound_dsp(&sq_fops, -1); if (sq_unit < 0) { - LEAVE(TRACE_ON,"sq_init"); return; } - /* whatever you like as startup mode for /dev/dsp, - * (/dev/audio hasn't got a startup mode). note that - * once changed a new open() will *not* restore these! - */ - sound.dsp.format = AFMT_S16_LE; - - sound.dsp.stereo = 0; - sound.dsp.size = 16; - - /* set minimum rate possible without expanding */ - switch (sound.mach.type) { - case DMASND_COLLIE: - sound.dsp.speed = 8000; - break; - } - - /* before the first open to /dev/dsp this wouldn't be set */ - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound.trans = &transCollie; - - CollieSetFormat(sound.dsp.format); - sound_silence(); - LEAVE(TRACE_ON,"sq_init"); + sound.format = AFMT_S16_LE; + sound.stereo = 1; + sound.speed = 44100; + + CollieSetFormat(AFMT_S16_LE); + Collie_audio_power_off(); + output_stream.buf=output_stream.buffers=NULL; } /* @@ -2816,9 +1414,7 @@ char *buffer = state.buf; int len = 0; - ENTER(TRACE_ON,"state_open"); if (state.busy) { - LEAVE(TRACE_ON,"state_open"); return -EBUSY; } @@ -2828,8 +1424,8 @@ len += sprintf(buffer+len, " COLLIE DMA sound driver:\n"); - len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format); - switch (sound.soft.format) { + len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.format); + switch (sound.format) { case AFMT_MU_LAW: len += sprintf(buffer+len, " (mu-law)"); break; @@ -2857,22 +1453,19 @@ } len += sprintf(buffer+len, "\n"); len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n", - sound.soft.speed, sound.hard.speed); + sound.speed, sound.speed); len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n", - sound.soft.stereo, - sound.soft.stereo ? "stereo" : "mono"); + sound.stereo, + sound.stereo ? "stereo" : "mono"); state.len = len; - LEAVE(TRACE_ON,"state_open"); return 0; } static int state_release(struct inode *inode, struct file *file) { - ENTER(TRACE_ON,"state_release"); state.busy = 0; MOD_DEC_USE_COUNT; - LEAVE(TRACE_ON,"state_release"); return 0; } @@ -2881,19 +1474,15 @@ loff_t *ppos) { int n = state.len - state.ptr; - ENTER(TRACE_ON,"state_read"); if (n > count) n = count; if (n <= 0) { - LEAVE(TRACE_ON,"state_read"); return 0; } if (copy_to_user(buf, &state.buf[state.ptr], n)) { - LEAVE(TRACE_ON,"state_read"); return -EFAULT; } state.ptr += n; - LEAVE(TRACE_ON,"state_read"); return n; } @@ -2909,20 +1498,11 @@ static void __init state_init(void) { -#ifndef MODULE - int state_unit; -#endif - ENTER(TRACE_ON,"state_unit"); state_unit = register_sound_special(&state_fops, SND_DEV_STATUS); if (state_unit < 0) { - LEAVE(TRACE_ON,"state_unit"); return; } state.busy = 0; - - // printk("state_init : ret \n"); - LEAVE(TRACE_ON,"state_unit"); - } @@ -2930,8 +1510,6 @@ static long long sound_lseek(struct file *file, long long offset, int orig) { - ENTER(TRACE_ON,"sound_lseek"); - LEAVE(TRACE_ON,"sound_lseek"); return -ESPIPE; } @@ -2941,96 +1519,41 @@ static int collie_sound_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) { - ENTER(TRACE_PM,"collie_sound_pm_callback"); switch (req) { case PM_SUSPEND: #ifdef COLLIE_TRY_ONE disable_irq(IRQ_GPIO_nREMOCON_INT); #endif -#ifdef TRY_DELAY_OFF /* H.Hayami SHARP 2001.12.19 */ - collieDoDelayedSilence(); - collieCancelDelayedSilence(); -#endif - if (audio_wr_refcount == 1) { - Collie_volume_off(); - Collie_hard_mute_on(); - Collie_soft_mute_on(); - sa1100_dma_sleep((dmach_t)COLLIE_SOUND_DMA_CHANNEL); - -#if 0 /* H.Hayami SHARP 2001.12.18 */ -#if !defined(CONFIG_COLLIE_TS) && !defined(CONFIG_COLLIE_TR0) && \ - !defined(CONFIG_COLLIE_TR1) && !defined(CONFIG_COLLIE_DEV) - Collie_volume_off(); -#endif -#endif - Collie_OP_SHDN_off(); - Collie_soft_DAC_off(); - Collie_paif_off(); - Collie_audio_clock_off(); - //Collie_MIC_on(); - Collie_DAC_off(); - Collie_AMP_off(); - } else { - sa1100_dma_sleep((dmach_t)COLLIE_SOUND_DMA_CHANNEL); - } - Collie_sound_hard_term(); + sa1100_dma_sleep((dmach_t)COLLIE_SOUND_DMA_CHANNEL); + Collie_audio_power_off(); break; case PM_RESUME: -/***** DEBUG *****g -printk("collie_sound_pm_callback: audio_wr_refcount=%d\n", audio_wr_refcount); -*****************/ + #ifdef COLLIE_TRY_ONE enable_irq(IRQ_GPIO_nREMOCON_INT); #endif - - Collie_sound_hard_init(); - - if (audio_wr_refcount == 1) { - collie_resume = 1; - - Collie_audio_power_on(); - - sa1100_dma_wakeup((dmach_t)COLLIE_SOUND_DMA_CHANNEL); -#if 0 /* H.Hayami SHARP 2001.12.18 */ - Collie_soft_mute_off(); - Collie_hard_mute_off(); -#endif - } else { + Collie_sound_hard_init(); /* this needs to be done! */ + collie_resume = 1; + Collie_audio_power_off(); + if (audio_wr_refcount) Collie_audio_power_on(); + if (collie_recording) Collie_recording_on(); + sa1100_dma_wakeup((dmach_t)COLLIE_SOUND_DMA_CHANNEL); #ifdef COLLIE_TRY_ONE - if ( !( GPLR & GPIO_nREMOCON_INT ) ) + if ( !( GPLR & GPIO_nREMOCON_INT ) ) Collie_DAC_on(); #endif - sa1100_dma_wakeup((dmach_t)COLLIE_SOUND_DMA_CHANNEL); - } - - break; - } - LEAVE(TRACE_PM,"collie_sound_pm_callback"); return 0; } #endif #ifdef COLLIE_TRY_ONE - -static void collie_audio_on(void) -{ - while(1) { - sleep_on(&audio_on); - - /* DAC ON */ - Collie_DAC_on(); - // printk("call audio on \n"); - - } -} - void Collie_rc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - // printk("int !\n"); - wake_up(&audio_on); + headphone=!headphone; + printk("%s headphone \n",headphone ? "connected" : "disconnected"); } #endif @@ -3038,113 +1561,85 @@ int __init Collie_sound_init(void) { - int has_sound = 0; - - - ENTER(TRACE_ON,"Collie_sound_init"); - has_sound = 1; - sound.mach = machCollie; - - if (!has_sound) { - LEAVE(TRACE_ON,"Collie_sound_init"); - return -1; - } - -#ifdef TRY_DELAY_OFF /* H.Hayami SHARP 2001.12.19 */ - sema_init(&df_sem, 1); - kernel_thread(collieDelayedSilence, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD); -#endif - Collie_sound_hard_init(); - - if (!sound.mach.irqinit()) { + if (!CollieIrqInit()) { printk("Sound driver: Interrupt initialization failed\n"); - LEAVE(TRACE_ON,"Collie_sound_init"); return -1; } - - /* Set up sound queue, /dev/audio and /dev/dsp. */ - /* Set default settings. */ sq_init(); - /* Set up /dev/sndstat. */ state_init(); - /* Set up /dev/mixer. */ mixer_init(); - #ifdef MODULE irq_installed = 1; #endif - printk("Collie Sound Driver Installed\n"); - #ifdef CONFIG_PM collie_sound_pm_dev = pm_register(PM_SYS_DEV, 0, collie_sound_pm_callback); #endif - - #ifdef COLLIE_TRY_ONE /* enable int sw */ collie_rc_set_int_mode(); - /* GPIO15(int):IN, GPIO18(sw):OUT */ GPDR = ((GPDR)&~GPIO_nREMOCON_INT)|GPIO_REMOCON_ADC_SW; - /* GPIO15,18:not Alternate */ GAFR &= ~(GPIO_nREMOCON_INT|GPIO_REMOCON_ADC_SW); - + /* Initialize headphone state */ + headphone=!(GPLR & GPIO_nREMOCON_INT); /* GPIO15:Falling Edge */ - set_GPIO_IRQ_edge(GPIO_nREMOCON_INT, GPIO_FALLING_EDGE); - + set_GPIO_IRQ_edge(GPIO_nREMOCON_INT, GPIO_BOTH_EDGES); /* Register interrupt handler */ if ( request_irq(IRQ_GPIO_nREMOCON_INT, Collie_rc_interrupt, - SA_INTERRUPT, "INSERT-HEADPHONE", Collie_rc_interrupt)) { - printk("%s: request_irq(%d) failed.\n", - __FUNCTION__, IRQ_GPIO_nREMOCON_INT); - } + SA_INTERRUPT, "headphone", 0)) { + printk("headphone: request_irq failed.\n"); - /* Make threads */ - kernel_thread(collie_audio_on, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD); + } + printk("Requested irq collie_rc succesfully (headphone) \n"); + printk("Headphone is now %s\n",headphone ? "connected" : "disconnected"); #endif - - LEAVE(TRACE_ON,"Collie_sound_init"); + Collie_audio_power_on(); // decreasing rec. noise? + Collie_audio_power_off(); return 0; } -module_init(Collie_sound_init); - - #ifdef MODULE - -int init_module(void) +static int collie_ssp_init_module(void) { - ENTER(TRACE_ON,"init_module"); Collie_sound_init(); - LEAVE(TRACE_ON,"init_module"); return 0; } -void cleanup_module(void) +static void collie_ssp_cleanup_module(void) { - ENTER(TRACE_ON,"cleanup_module"); +#ifdef CONFIG_PM + pm_unregister(collie_sound_pm_dev); +#endif if (irq_installed) { - sound_silence(); - sound.mach.irqcleanup(); + sa1100_dma_stop(COLLIE_SOUND_DMA_CHANNEL); + sa1100_dma_flush_all(COLLIE_SOUND_DMA_CHANNEL); + Collie_audio_power_off(); + sa1100_free_dma(COLLIE_SOUND_DMA_CHANNEL); } - - sq_release_buffers(); - - if (mixer_unit >= 0) - unregister_sound_mixer(mixer_unit); - if (state_unit >= 0) - unregister_sound_special(state_unit); - if (sq_unit >= 0) - unregister_sound_dsp(sq_unit); - LEAVE(TRACE_ON,"cleanup_module"); -} - +#ifdef COLLIE_TRY_ONE + free_irq(IRQ_GPIO_nREMOCON_INT,0); +#endif + unregister_sound_mixer(mixer_unit); + unregister_sound_special(state_unit); + unregister_sound_dsp(sq_unit); + printk("collie_ssp has to go now, see you later!\n"); +} + +module_init(collie_ssp_init_module); +module_exit(collie_ssp_cleanup_module); +MODULE_DESCRIPTION("Collie 16bit sound driver"); +MODULE_AUTHOR("SHARP"); +MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(Collie_recording_off); +EXPORT_SYMBOL(Collie_recording_on); +EXPORT_SYMBOL(collie_recording); #endif /* MODULE */ + diff -Nuar linux-2.4.18/drivers/sound/collie_tc35143af.c linux-2.4.18p/drivers/sound/collie_tc35143af.c --- linux-2.4.18/drivers/sound/collie_tc35143af.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.18p/drivers/sound/collie_tc35143af.c 2004-10-13 15:26:20.336631864 +0200 @@ -0,0 +1,1457 @@ +/* + TODO + + buzzer compatibility is not fool proof - if an app starts sending buzzer ioctls + and then write or read, nothing good will happen / but this api is obsolote anyway + + mixer_ioctls missing: write/read_mic/igain (there are sane defaults for those) + + fixed samplerate at 22050hz (mono,s16_le), although it can be changed + between 8000-22050hz hardwarewise + + + DONE + + buffers are only allocated once, and freed when module is unloaded + mute left channel when duplex playing & recording + cleanup + depend on collie_ssp, and call needed functions when needed + (recording noise should be gone too as a consequence) + lineo's getospace incorporated (getispace left alone) + "optimized" default fragsize and number, so there is now no clicking all the time + commented out scndctl_dsp_setfragment so that no application can set bad settings (eg.xmms) + if you start reading from this device, than it won't let you write later unless you close it first + (and vica-versa) + speaker is muted if nothing is playing, so noise is gone + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#undef DEBUG +#ifdef DEBUG +#define DPRINTK( x... ) printk( ##x ) +#else +#define DPRINTK( x... ) +#endif + +extern int collie_recording; +extern void Collie_recording_on(void); +extern void Collie_recording_off(void); + +int collie_tc35143f_irq = -1; +int collie_tc35143f_input_irq = -1; + +#define COLLIE_BUZZER_DMA_CHANNEL (collie_tc35143f_irq) +#define COLLIE_BUZZER_DMA_CHANNEL_INPUT (collie_tc35143f_input_irq) +#define COLLIE_GPIO_MIC GPIO_GPIO (17) + +#define SND_NDEVS 256 /* Number of supported devices */ +#define SND_DEV_CTL 0 /* Control port /dev/mixer */ +#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM synthesizer and MIDI output) */ +#define SND_DEV_MIDIN 2 /* Raw midi access */ +#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */ +#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */ +#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */ +#define SND_DEV_STATUS 6 /* /dev/sndstat */ +/* #7 not in use now. Was in 2.4. Free for use after v3.0. */ +#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */ +#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */ +#define SND_DEV_PSS SND_DEV_SNDPROC + +#ifdef MODULE +static int sq_unit = -1; +static int mixer_unit = -1; +static int state_unit = -1; +static int irq_installed = 0; +#endif /* MODULE */ + +#ifdef CONFIG_PM +static struct pm_dev* collie_sound_pm_dev; +#endif + +/*** Some declarations ***********************************************/ +static int collie_buzzer_volume = 100; +static int audio_igain = 0; +static int audio_iamp = 0x05; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) +static struct ucb1x00 * ucbstruct; +#endif +static int TC35143f_control_reg_a; +static int TC35143f_control_reg_b; +static int TC35143f_mode; + +#define AUDIO_NBFRAGS_DEFAULT 32 +#define AUDIO_FRAGSIZE_DEFAULT 2048 + +typedef struct { + int size; /* buffer size */ + char *start; /* points to actual buffer */ + dma_addr_t dma_addr; /* physical buffer address */ + struct semaphore sem; /* down before touching the buffer */ + int master; /* master owner for buffer allocation */ + u_int idx; /* buffer index, so that we know which buffer was sent last*/ +} audio_buf_t; + +typedef struct { + audio_buf_t *buffers; /* pointer to audio buffer structures */ + audio_buf_t *buf; /* current buffer used by read/write */ + u_int buf_idx; /* index for the pointer above... */ + u_int fragsize; /* fragment i.e. buffer size */ + u_int nbfrags; /* nbr of fragments i.e. buffers */ +} audio_stream_t; + +static audio_stream_t output_stream, input_stream; + +#define NEXT_BUF(_s_,_b_) { \ + (_s_)->_b_##_idx++; \ + (_s_)->_b_##_idx %= (_s_)->nbfrags; \ + (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_idx; } + +/* Current specs for incoming audio data */ +static u_int audio_fragsize=AUDIO_FRAGSIZE_DEFAULT; +static u_int audio_nbfrags=AUDIO_NBFRAGS_DEFAULT; + +static volatile int audio_refcount; /* nbr of concurrent open() for playback */ +typedef enum { REC,PLAY,NA,BUZZ } collie_tc_status_t; +static collie_tc_status_t collie_tc_status; +int collie_tc_muted; + +#define IOCTL_IN(arg, ret) \ + do { int error = get_user(ret, (int *)(arg)); \ + if (error) return error; \ + } while (0) +#define IOCTL_OUT(arg, ret) ioctl_return((int *)(arg), ret) + +/*** "Translations" ************************************************************/ + +static ssize_t collie_ct_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static signed short ct_out=0; +/*** Low level stuff *********************************************************/ + + +typedef struct { + int format; /* AFMT_* */ + int stereo; /* 0 = mono, 1 = stereo */ + int size; /* 8/16 bit*/ + int speed; /* speed */ + int volume; +} SETTINGS; + +static SETTINGS sound; + +#ifdef CONFIG_PM +//extern int autoPowerCancel; +#endif + +static void Collie_Set_Volume(int volume); +static int Collie_Get_Volume(void); +static int CollieIrqInit(void); +static int CollieSetFormat(int format); +static void Collie_sq_interrupt(void*, int); +static int sq_allocate_buffers(audio_stream_t*); +static void sq_release_buffers(audio_stream_t*); + +/*** Mid level stuff *********************************************************/ +static int sound_set_speed(int speed); + +/* + * /dev/mixer abstraction + */ + +struct sound_mixer { + int busy; +}; + +static struct sound_mixer mixer; + +/* + * /dev/sndstat + */ + +/*** Common stuff ********************************************************/ + +static long long sound_lseek(struct file *file, long long offset, int orig); +static inline int ioctl_return(int *addr, int value) +{ + if (value < 0) { + return(value); + } + return put_user(value, addr)? -EFAULT: 0; +} + +static void wait_ms(int ten_ms) +{ + schedule_timeout(ten_ms); +} + +/*** Translation ************************************************************/ + +static ssize_t collie_ct_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + signed short *fp = (unsigned short *) &frame[*frameUsed]; + signed short *up = (unsigned short *) userPtr; + + frameLeft >>= 1; + userCount >>= 1; + used = count = (userCount < frameLeft) ? userCount : frameLeft; + + while (count > 0) { + signed short data; + if (get_user(data, up++)) { + return -EFAULT; + } /* lowpass filtering, not that it matters much - something is resonating inside the Zaurus at high frequencies ? */ + *fp++ = ct_out = (short)( ( (long)data + (long)ct_out ) >> 1LL ); + count--; + } + + *frameUsed += used * 2; + return used * 2; +} + +/*** HARDWARE dependent stuff *********************************************************/ +#define VOL_THRES 10 +#define CODEC_ASD_NUMERATOR 13 +/*~ (9216000 / ( 32 * 22050 )) */ + +static int Collie_Sampling_value(void) +{ + int asd = CODEC_ASD_NUMERATOR; + DPRINTK("Collie_Sampling_value %x\n",asd); + return asd; +} + +static void Collie_sound_hard_init(void) +{ + int asd; + + DPRINTK("CollieInit\n"); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_enable(ucbstruct); + ucb1x00_io_set_dir(ucbstruct,0, TC35143_GPIO_BUZZER_BIAS); + ucb1x00_disable(ucbstruct); +#else + ucb1200_set_io_direction(TC35143_GPIO_BUZZER_BIAS, TC35143_IODIR_OUTPUT); +#endif + + DPRINTK("TC35143F Init"); + + // init MCP + asd = Collie_Sampling_value(); + Ser4MCCR0 &= ~MCCR0_MCE; + Ser4MCCR0 &= ~0xff; + Ser4MCCR0 |= (MCCR0_ARE | MCCR0_ATE |MCCR0_ADM | MCCR0_ECS | asd); + Ser4MCCR0 |= MCCR0_MCE; + Ser4MCSR = 0xffffffff; + + DPRINTK("Init MCP %x\n",Ser4MCCR0); +} + +static void Collie_audio_power_on(void) +{ + if ( collie_buzzer_volume > 100 ) collie_buzzer_volume = 100; + if ( collie_buzzer_volume < 0 ) collie_buzzer_volume = 0; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_enable(ucbstruct); +#endif + TC35143f_control_reg_a = ( TC35143_VDIV_22KHZ ); + TC35143f_control_reg_b = ( TC35143_VADMUTE | TC35143_VHSMUTE | ( 7 - collie_buzzer_volume / 13)); + TC35143f_mode = ( TC35143_VOFFCAN | TC35143_VCOF_22_OR_16KHZ ); + TC35143f_control_reg_a &= ~(TC35143_VINSEL_MASK | TC35143_VGAIN_MASK | TC35143_VAMP_MASK); + TC35143f_control_reg_a |= (TC35143_VINSEL_VBIN2 | ((audio_igain & 0x3)<<11) | ((audio_iamp & 0x0f)<<7)); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_reg_write(ucbstruct,TC35143_CONTROL_REG_B , TC35143f_control_reg_b); + ucb1x00_reg_write(ucbstruct,TC35143_CONTROL_REG_A , TC35143f_control_reg_a); + ucb1x00_reg_write(ucbstruct,TC35143_MODE_REG , TC35143f_mode ); + ucb1x00_io_write(ucbstruct, TC35143_GPIO_BUZZER_BIAS,0); + ucb1x00_disable(ucbstruct); +#else + ucb1200_write_reg(TC35143_CONTROL_REG_B , TC35143f_control_reg_b ); + ucb1200_write_reg(TC35143_MODE_REG , TC35143f_mode ); + ucb1200_write_reg(TC35143_CONTROL_REG_A , TC35143f_control_reg_a ); + ucb1200_set_io(TC35143_GPIO_BUZZER_BIAS, TC35143_IODAT_HIGH); +#endif + collie_tc_muted=1; +} + +static void Collie_audio_power_off(void){ /* Disable sound only */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_enable(ucbstruct); + ucb1x00_io_write(ucbstruct,0, TC35143_GPIO_BUZZER_BIAS); +#else + ucb1200_set_io(TC35143_GPIO_BUZZER_BIAS, TC35143_IODAT_LOW); +#endif + + TC35143f_control_reg_a = ( TC35143_VDIV_22KHZ ); + TC35143f_control_reg_b = ( TC35143_ALL_MUTE ); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_reg_write(ucbstruct,TC35143_CONTROL_REG_B , TC35143f_control_reg_b); + ucb1x00_reg_write(ucbstruct,TC35143_CONTROL_REG_A , TC35143f_control_reg_a); + ucb1x00_disable(ucbstruct); +#else + ucb1200_write_reg(TC35143_CONTROL_REG_B , TC35143f_control_reg_b ); + ucb1200_write_reg(TC35143_CONTROL_REG_A , TC35143f_control_reg_a ); +#endif +} + +static void collie_tc_mute_on(void){ + unsigned int reg_b; + unsigned int reg_a; + + if (!collie_tc_muted) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_enable(ucbstruct); + reg_b = ucb1x00_reg_read(ucbstruct,TC35143_CONTROL_REG_B); + reg_a = ucb1x00_reg_read(ucbstruct,TC35143_CONTROL_REG_A); +#else + reg_b = ucb1200_read_reg(TC35143_CONTROL_REG_B); + reg_a = ucb1200_read_reg(TC35143_CONTROL_REG_A); +#endif + reg_b &= ~TC35143_VOUT1_EN; + reg_a &= ~TC35143_VOUT2_EN; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_reg_write(ucbstruct,TC35143_CONTROL_REG_A, reg_a); + ucb1x00_reg_write(ucbstruct,TC35143_CONTROL_REG_B, reg_b); + ucb1x00_disable(ucbstruct); +#else + ucb1200_write_reg(TC35143_CONTROL_REG_A, reg_a); + ucb1200_write_reg(TC35143_CONTROL_REG_B, reg_b); +#endif + collie_tc_muted=1; + } +} + +static void collie_tc_mute_off(void){ + unsigned int reg_b; + unsigned int reg_a; + + if (collie_tc_muted) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_enable(ucbstruct); + reg_b = ucb1x00_reg_read(ucbstruct,TC35143_CONTROL_REG_B); + reg_a = ucb1x00_reg_read(ucbstruct,TC35143_CONTROL_REG_A); +#else + reg_b = ucb1200_read_reg(TC35143_CONTROL_REG_B); + reg_a = ucb1200_read_reg(TC35143_CONTROL_REG_A); +#endif + reg_b |= TC35143_VOUT1_EN ; + reg_b &= ~7; + reg_b |= ( 7 - collie_buzzer_volume / 13); + reg_a |= TC35143_VOUT2_EN; + reg_a &= ~(TC35143_VGAIN_MASK | TC35143_VAMP_MASK); + reg_a |= (((audio_igain & 0x3)<<11) | ((audio_iamp & 0x0f)<<7)); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_reg_write(ucbstruct,TC35143_CONTROL_REG_A, reg_a); + ucb1x00_reg_write(ucbstruct,TC35143_CONTROL_REG_B, reg_b); + ucb1x00_disable(ucbstruct); +#else + ucb1200_write_reg(TC35143_CONTROL_REG_A, reg_a); + ucb1200_write_reg(TC35143_CONTROL_REG_B, reg_b); +#endif + collie_tc_muted=0; + } +} + + +static void Collie_volume_set(int dest) +{ + if (collie_buzzer_volume==dest) return; + collie_buzzer_volume=dest; + collie_tc_mute_on(); + collie_tc_mute_off(); +} + + +/*********** GENERAL stuff, same as collie_ssp *******************************/ + + +static void Collie_Set_Volume(int volume) +{ + sound.volume = volume & 0xff; + sound.volume += ( volume & 0xff00 >> 8); + sound.volume >>=1; + if (sound.volume>100) sound.volume=100; +} + +static int Collie_Get_Volume(void) +{ + return ( sound.volume << 8 | sound.volume ); +} + +static void Collie_sq_interrupt(void* id, int size) +{ + audio_buf_t *b = (audio_buf_t *) id; + audio_buf_t *b2 = output_stream.buffers + ((b->idx + 1) % output_stream.nbfrags); + + /* If this is the last buffer for know, let's mute the speaker */ + if (!down_trylock(&b2->sem)) { + collie_tc_mute_on(); + up(&b2->sem); + } + + /* + * Current buffer is sent: wake up any process waiting for it. + */ + up(&b->sem); + /* And any process polling on write. */ + wake_up_interruptible(&b->sem.wait); + + DPRINTK("Collie_sq_interrupt \n"); +} + +static void Collie_sq_input_interrupt(void* id, int size) +{ + audio_buf_t *b = (audio_buf_t *) id; + /* + * Current buffer is sent: wake up any process waiting for it. + */ + b->size = size; + up(&b->sem); + /* And any process polling on write. */ + wake_up_interruptible(&b->sem.wait); + /* And indicate which was the last buffer sent */ + + DPRINTK("Collie_sq_input_interrupt \n"); +} + + +static int __init CollieIrqInit(void) +{ + int err; + + err = sa1100_request_dma(&COLLIE_BUZZER_DMA_CHANNEL, "buzzer output", + DMA_Ser4MCP0Wr); + + if (err) { + return 0; + } + printk("collie_tc35143f_irq=%d\n", collie_tc35143f_irq); + + err = sa1100_request_dma(&COLLIE_BUZZER_DMA_CHANNEL_INPUT, "buzzer input", + DMA_Ser4MCP0Rd); + + if (err) { + return 0; + } + printk("collie_tc35143f_input_irq=%d\n", collie_tc35143f_input_irq); + + + sa1100_dma_set_callback(COLLIE_BUZZER_DMA_CHANNEL, + (dma_callback_t)Collie_sq_interrupt); + + sa1100_dma_set_callback(COLLIE_BUZZER_DMA_CHANNEL_INPUT, + (dma_callback_t)Collie_sq_input_interrupt); + + + sa1100_dma_stop(COLLIE_BUZZER_DMA_CHANNEL); + Collie_audio_power_off(); + sa1100_dma_stop(COLLIE_BUZZER_DMA_CHANNEL_INPUT); + sa1100_dma_flush_all(COLLIE_BUZZER_DMA_CHANNEL); + return(1); +} + +static int CollieSetFormat(int format) +{ + int size; + + switch (format) { + case AFMT_QUERY: + return(sound.format); + default: /* This is the only one supported by the hardware it seems */ + size = 16; + format = AFMT_S16_LE; + } + sound.format = format; + sound.size = size; + + return(format); +} + + +static int sound_set_speed(int speed) +{ + if (speed < 0) { + return(sound.speed); + } + sound.speed=22050; + return(sound.speed); +} + +/* Higher level stuff ************************************************/ + +/* + * /dev/mixer abstraction + */ + +static int mixer_open(struct inode *inode, struct file *file) +{ + MOD_INC_USE_COUNT; + mixer.busy = 1; + return 0; +} + +static int mixer_release(struct inode *inode, struct file *file) +{ + mixer.busy = 0; + MOD_DEC_USE_COUNT; + return 0; +} + + +static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg) +{ + int data; + + DPRINTK("Got mixer ioctl \n"); + + switch (cmd) { + case SOUND_MIXER_INFO: + DPRINTK("0\n"); + return 0; + case SOUND_OLD_MIXER_INFO: + DPRINTK("0\n"); + return 0; + + case SOUND_MIXER_READ_DEVMASK: + DPRINTK("1\n"); + return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_IGAIN ); + case SOUND_MIXER_READ_RECMASK: + DPRINTK("2\n"); + return IOCTL_OUT(arg, SOUND_MASK_MIC); + case SOUND_MIXER_READ_STEREODEVS: + DPRINTK("3\n"); + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_READ_CAPS: + DPRINTK("4\n"); + return IOCTL_OUT(arg, 0); + + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + Collie_Set_Volume(data); + DPRINTK("mix_io returning\n"); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_VOLUME: + DPRINTK("5\n"); + return IOCTL_OUT(arg, Collie_Get_Volume()); + case SOUND_MIXER_READ_TREBLE: + DPRINTK("6\n"); + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_WRITE_TREBLE: + DPRINTK("7\n"); + return IOCTL_OUT(arg, 0); + + case SOUND_MIXER_READ_BASS: + DPRINTK("6b\n"); + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_WRITE_BASS: + DPRINTK("7b\n"); + return IOCTL_OUT(arg, 0); + + + case SOUND_MIXER_WRITE_MIC: + case SOUND_MIXER_WRITE_IGAIN: + DPRINTK("8\n"); + return IOCTL_OUT(arg, 100); + case SOUND_MIXER_READ_MIC: + case SOUND_MIXER_READ_IGAIN: + DPRINTK("9\n"); + return IOCTL_OUT(arg, 0); + + case SOUND_MIXER_READ_SPEAKER: + DPRINTK("10\n"); + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_WRITE_SPEAKER: + DPRINTK("11\n"); + return IOCTL_OUT(arg, 0); + default: + DPRINTK("12 %d\n",cmd); + return -ENOSYS; + } + DPRINTK("EINVAL %d??\n",cmd); + return -EINVAL; +} + + +static struct file_operations mixer_fops = +{ + llseek: sound_lseek, + ioctl: mixer_ioctl, + open: mixer_open, + release: mixer_release, +}; + + +static void __init mixer_init(void) +{ + mixer_unit = register_sound_mixer(&mixer_fops, -1); + if (mixer_unit < 0) { + return; + } + mixer.busy = 0; + sound.volume = 100; + Collie_volume_set(sound.volume); +} + +/* This function initializes the buffer + */ + +static void sq_clean_buffers(audio_stream_t * s) +{ + int frag; + + sa1100_dma_flush_all(COLLIE_BUZZER_DMA_CHANNEL); + sa1100_dma_flush_all(COLLIE_BUZZER_DMA_CHANNEL_INPUT); + + s->nbfrags = audio_nbfrags; + s->fragsize = audio_fragsize; + + if (!s->buffers) + goto err; + + for (frag = 0; frag < s->nbfrags; frag++) { + audio_buf_t *b = &s->buffers[frag]; + b->size=0; + sema_init(&b->sem, 1); + } + s->buf_idx = 0; + s->buf = &s->buffers[0]; + return; + +err: + printk("sound driver : where did the buffer go ??\n "); +} + +/* This function allocates the buffer structure array and buffer data space + * according to the current number of fragments and fragment size. + */ + +static int sq_allocate_buffers(audio_stream_t * s) +{ + int frag; + int dmasize = 0; + char *dmabuf = 0; + dma_addr_t dmaphys = 0; + + DPRINTK("sq_allocate_buffers\n"); + + if (s->buffers) { + return -EBUSY; + } + + s->nbfrags = audio_nbfrags; + s->fragsize = audio_fragsize; + + s->buffers = (audio_buf_t *) + kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL); + if (!s->buffers) + goto err; + memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags); + + for (frag = 0; frag < s->nbfrags; frag++) { + audio_buf_t *b = &s->buffers[frag]; + + /* + * Let's allocate non-cached memory for DMA buffers. + * We try to allocate all memory at once. + * If this fails (a common reason is memory fragmentation), + * then we allocate more smaller buffers. + */ + if (!dmasize) { + dmasize = (s->nbfrags - frag) * s->fragsize; + do { + dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA, + dmasize, + &dmaphys); + if (!dmabuf) + dmasize -= s->fragsize; + } while (!dmabuf && dmasize); + if (!dmabuf) + goto err; + b->master = dmasize; + } + + b->start = dmabuf; + b->dma_addr = dmaphys; + b->idx = frag; + sema_init(&b->sem, 1); + dmabuf += s->fragsize; + dmaphys += s->fragsize; + dmasize -= s->fragsize; + } + + s->buf_idx = 0; + s->buf = &s->buffers[0]; + + return 0; + +err: + printk("sound driver : unable to allocate audio memory\n "); + sq_release_buffers(s); + return -ENOMEM; +} + +/* + * This function frees all buffers + */ + +static void sq_release_buffers(audio_stream_t * s) +{ + DPRINTK("sq_release_buffers\n"); + + /* ensure DMA won't run anymore */ + sa1100_dma_flush_all(COLLIE_BUZZER_DMA_CHANNEL); + sa1100_dma_flush_all(COLLIE_BUZZER_DMA_CHANNEL_INPUT); + + if (s->buffers) { + int frag; + for (frag = 0; frag < s->nbfrags; frag++) { + if (!s->buffers[frag].master) + continue; + consistent_free(s->buffers[frag].start, + s->buffers[frag].master, + s->buffers[frag].dma_addr); + } + kfree(s->buffers); + s->buffers = NULL; + } + + s->buf_idx = 0; + s->buf = NULL; +} + +static int audio_recording(audio_stream_t * s) +{ + int i; + unsigned int reg_b; + + if (!collie_recording) { + /* + * Set TC35143 Audio in enable + */ +//// DPRINTK("audio_recording : audio in enable\n"); +//// reg_b = ucb1200_read_reg(TC35143_CONTROL_REG_B); +//// reg_b &= ~(TC35143_VADMUTE); +//// reg_b |= (TC35143_VIN_EN | TC35143_VCLP_CLR); +//// ucb1200_write_reg(TC35143_CONTROL_REG_B, reg_b); + + /* + * We must ensure there is an output stream at any time while + * recording since this is how the TC35143 gets its clock. + * So if there is no playback data to send, the output DMA will + * spin with all zeroes. + */ + + Collie_recording_on(); + collie_tc_mute_off(); /* This is needed for good volume */ + DPRINTK("audio_recording : sa1100_dma_set_spin\n"); + sa1100_dma_set_spin(COLLIE_BUZZER_DMA_CHANNEL, + (dma_addr_t) FLUSH_BASE_PHYS, 2048); + + /* + * Since we just allocated all buffers, we must send them to + * the DMA code before receiving data. + */ + DPRINTK("audio_recording : for loop\n"); + for (i = 0; i < s->nbfrags; i++) { + audio_buf_t *b = s->buf; + down(&b->sem); + sa1100_dma_queue_buffer(COLLIE_BUZZER_DMA_CHANNEL_INPUT, (void *) b, + b->dma_addr, s->fragsize); + NEXT_BUF(s, buf); + } + DPRINTK("audio_recording : End for loop\n"); + + /* + * Set TC35143 Audio in enable + */ + DPRINTK("audio_recording : audio in enable\n"); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_enable(ucbstruct); + ucb1x00_io_write(ucbstruct, 0, TC35143_GPIO_BUZZER_BIAS); + reg_b = ucb1x00_reg_read(ucbstruct,TC35143_CONTROL_REG_B); +#else + ucb1200_set_io(TC35143_GPIO_BUZZER_BIAS, TC35143_IODAT_LOW); + reg_b = ucb1200_read_reg(TC35143_CONTROL_REG_B); +#endif + reg_b &= ~(TC35143_VADMUTE); + reg_b |= (TC35143_VIN_EN | TC35143_VCLP_CLR); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucb1x00_reg_write(ucbstruct,TC35143_CONTROL_REG_B, reg_b); + ucb1x00_disable(ucbstruct); +#else + ucb1200_write_reg(TC35143_CONTROL_REG_B, reg_b); +#endif + } + return 0; +} + + +static int sq_read(struct file *file, char *buffer, + size_t count, loff_t * ppos) +{ + char *buffer0 = buffer; + audio_stream_t *s = &input_stream; + int chunksize, ret = 0; + + DPRINTK("audio_read: count=%d\n", count); + + + ret = audio_recording(s); + + if ((collie_tc_status!=NA) && (collie_tc_status!=REC)) + return -EPERM; + collie_tc_status=REC; + + if (ret) + return ret; + + /* be sure to have a full sample byte count */ + count &= ~0x03; + +// DPRINTK("audio_read : Start while loop\n"); + while (count > 0) { + audio_buf_t *b = s->buf; + + /* Wait for a buffer to become full */ + if (file->f_flags & O_NONBLOCK) { +// DPRINTK("audio_read : down_trylock\n"); + ret = -EAGAIN; + if (down_trylock(&b->sem)) + break; + } else { +// DPRINTK("audio_read : down_interruptible\n"); + ret = -ERESTARTSYS; + if (down_interruptible(&b->sem)) + break; + } + + /* Grab data from the current buffer */ + chunksize = b->size; + if (chunksize > count) + chunksize = count; + DPRINTK("read %d from %d\n", chunksize, s->buf_idx); + + if (copy_to_user(buffer, b->start + s->fragsize - b->size, chunksize)) { + up(&b->sem); + DPRINTK("not copied to buffer \n"); + return -EFAULT; + } + DPRINTK("copied to buffer \n"); + + b->size -= chunksize; + buffer += chunksize; + count -= chunksize; + + if (b->size > 0) { + up(&b->sem); + break; + } + + /* Make current buffer available for DMA again */ + sa1100_dma_queue_buffer(COLLIE_BUZZER_DMA_CHANNEL_INPUT, (void *) b, + b->dma_addr, s->fragsize); + NEXT_BUF(s, buf); + } +// DPRINTK("audio_read : End while loop\n"); + + if ((buffer - buffer0)) + ret = buffer - buffer0; +// DPRINTK("audio_read: return=%d\n", ret); + return ret; +} + +static ssize_t sq_write(struct file *file, const char *src, size_t uLeft, + loff_t *ppos) +{ + const char *buffer0 = src; + audio_stream_t *s = &output_stream; + u_char *dest; + ssize_t uUsed, bUsed, bLeft, ret = 0; + + DPRINTK("sq_write: uLeft=%d\n", uLeft); + + if ((collie_tc_status!=NA) && (collie_tc_status!=PLAY)) + return -EPERM; + + collie_tc_status=PLAY; + + if (!s->buffers && sq_allocate_buffers(s)) { + return -ENOMEM; + } + + +#ifdef CONFIG_PM + /* Auto Power off cancel */ +// autoPowerCancel = 0; +#endif + + collie_tc_mute_off(); + while (uLeft > 0) { + audio_buf_t *b = s->buf; + + /* Wait for a buffer to become free */ + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + if (down_trylock(&b->sem)) { + break; + } + } else { + ret = -ERESTARTSYS; + if (down_interruptible(&b->sem)) { + break; + } + } + + dest = b->start + b->size; + bUsed = 0; + bLeft = s->fragsize - b->size; + + if (collie_ct_s16) { + uUsed = collie_ct_s16(src, uLeft, dest, &bUsed, bLeft); + cpu_cache_clean_invalidate_range((unsigned long)dest, + (unsigned long)(dest+(audio_fragsize)), 0); + } else { + return -EFAULT; + } + + if (uUsed < 0) { + up(&b->sem); + return -EFAULT; + } + src += uUsed; + uLeft -= uUsed; + b->size += bUsed; + + if (b->size < s->fragsize) { + up(&b->sem); + break; + } + + /* Send current buffer to dma */ + sa1100_dma_queue_buffer(COLLIE_BUZZER_DMA_CHANNEL, + (void *) b, b->dma_addr, b->size); + + Collie_volume_set(sound.volume); + + b->size = 0; /* indicate that the buffer has been sent */ + NEXT_BUF(s, buf); + } + + if ((src - buffer0)) + ret = src - buffer0; + DPRINTK("sq_write: return=%d\n", ret); + return ret; +} + +static unsigned int sq_poll(struct file *file, + struct poll_table_struct *wait) +{ + unsigned int mask = 0; + int i,ret; + + DPRINTK("sq_poll(): mode=%s%s\n", + (file->f_mode & FMODE_READ) ? "r" : "", + (file->f_mode & FMODE_WRITE) ? "w" : ""); + + if ((file->f_mode & FMODE_READ) && (file->f_mode & FMODE_WRITE) && (collie_tc_status==NA)) + return mask; + + if ((file->f_mode & FMODE_WRITE) && (collie_tc_status!=REC)) { + if (!output_stream.buffers + && sq_allocate_buffers(&output_stream)) { + return -ENOMEM; + } + poll_wait(file, &output_stream.buf->sem.wait, wait); + } + + if ((file->f_mode & FMODE_WRITE) && (collie_tc_status!=REC)) { + for (i = 0; i < output_stream.nbfrags; i++) { + if (atomic_read(&output_stream.buffers[i].sem.count) > 0) + mask |= POLLOUT | POLLWRNORM; + } + } + + if ((file->f_mode & FMODE_READ) && (collie_tc_status!=PLAY)) { + ret = audio_recording(&input_stream); + if (ret<0) { + return ret; + } + poll_wait(file, &input_stream.buf->sem.wait, wait); + } + + if ((file->f_mode & FMODE_READ) && (collie_tc_status!=PLAY)) { + for (i = 0; i < input_stream.nbfrags; i++) { + if (atomic_read(&input_stream.buffers[i].sem.count) > 0) + mask |= POLLIN | POLLRDNORM; + } + } + + DPRINTK("sq_poll() returned mask of %s%s\n", + (mask & POLLIN) ? "r" : "", + (mask & POLLOUT) ? "w" : ""); + + return mask; +} + +static int sq_open(struct inode *inode, struct file *file) +{ + DPRINTK("sq_open\n"); + + if (audio_refcount) { + DPRINTK(" sq_open EBUSY\n"); + return -EBUSY; + } + + switch (file->f_flags & O_ACCMODE) { + case O_WRONLY: + collie_tc_status=PLAY; + sa1100_dma_stop(COLLIE_BUZZER_DMA_CHANNEL_INPUT); + break; + case O_RDONLY: + collie_tc_status=REC; + break; + case O_RDWR: + collie_tc_status=NA; + break; + default: + DPRINTK(" sq_open EINVAL\n"); + return -EINVAL; + } + + MOD_INC_USE_COUNT; + audio_refcount++; + + audio_fragsize = AUDIO_FRAGSIZE_DEFAULT; + audio_nbfrags = AUDIO_NBFRAGS_DEFAULT; + sq_clean_buffers(&input_stream); + sq_clean_buffers(&output_stream); + Collie_audio_power_on(); + DPRINTK("Going back\n"); + return 0; +} + +static int sq_post(void) +{ + audio_stream_t *s = &output_stream; + audio_buf_t *b = s->buf; + + DPRINTK("sq_post\n"); + + if (!s->buffers) { + return 0; + } + + /* Send half-full buffers */ + if (b->size != 0) { + DPRINTK("half-full_buf\n"); + +#ifdef CONFIG_PM + /* Auto Power off cancel */ +// autoPowerCancel = 0; +#endif + + down(&b->sem); + sa1100_dma_queue_buffer(COLLIE_BUZZER_DMA_CHANNEL, + (void *) b, b->dma_addr, b->size); + b->size = 0; + NEXT_BUF(s, buf); + } + return 0; +} + +static int sq_fsync(void) +{ + audio_stream_t *s = &output_stream; + audio_buf_t *b = s->buf; + + DPRINTK("sq_fsync\n"); + + if (!s->buffers) { + return 0; + } + + /* Send half-full buffers */ + if (b->size != 0) { + DPRINTK("half-full_buf\n"); + +#ifdef CONFIG_PM + /* Auto Power off cancel */ +// autoPowerCancel = 0; +#endif + + down(&b->sem); + sa1100_dma_queue_buffer(COLLIE_BUZZER_DMA_CHANNEL, + (void *) b, b->dma_addr, b->size); + b->size = 0; + NEXT_BUF(s, buf); + } + + /* + * Let's wait for the last buffer we sent i.e. the one before the + * current buf_idx. When we acquire the semaphore, this means either: + * - DMA on the buffer completed or + * - the buffer was already free thus nothing else to sync. + */ + b = s->buffers + ((s->nbfrags + s->buf_idx - 1) % s->nbfrags); + if (down_interruptible(&b->sem)) { + return -EINTR; + } + up(&b->sem); + return 0; +} + +static int sq_release(struct inode *inode, struct file *file) +{ + DPRINTK("speaker_sq_release\n"); + + switch (collie_tc_status) { + + case REC: + sa1100_dma_set_spin(COLLIE_BUZZER_DMA_CHANNEL,0,0); + sq_clean_buffers(&input_stream); + Collie_recording_off(); + break; + case PLAY: + sq_fsync(); + sq_clean_buffers(&output_stream); + break; + default: + break; + } + audio_refcount = 0; + collie_tc_status=NA; + sa1100_dma_stop(COLLIE_BUZZER_DMA_CHANNEL); + Collie_audio_power_off(); + sa1100_dma_stop(COLLIE_BUZZER_DMA_CHANNEL_INPUT); + MOD_DEC_USE_COUNT; + return 0; +} + +/* Buzzer compatibility */ +#include "colliebuzzer.h" + + +static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg) +{ + u_long fmt; + int data,ret; +// audio_buf_info abinfo; + + DPRINTK("Got ioctl %ld \n",cmd); + + switch (cmd) { + case 22144: + sq_write_buzzer(arg); + sq_fsync(); + return 0; + case SNDCTL_DSP_RESET: + switch (collie_tc_status) { + case REC: + sq_clean_buffers(&input_stream); + case PLAY: + sq_fsync(); + sq_clean_buffers(&output_stream); + default: + break; + } + return 0; + case SNDCTL_DSP_POST: + sq_post(); + return 0; + case SNDCTL_DSP_SYNC: + sq_fsync(); + return 0; + + /* ++TeSche: before changing any of these it's + * probably wise to wait until sound playing has + * settled down. */ + case SNDCTL_DSP_SPEED: +// sq_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, sound_set_speed(data)); + + case SOUND_PCM_READ_RATE: + return 0; + + case SNDCTL_DSP_STEREO: +// sq_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, 0); + case SNDCTL_DSP_CHANNELS: +// sq_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, 1); + case SNDCTL_DSP_SETFMT: +// sq_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, CollieSetFormat(data)); + case SNDCTL_DSP_GETFMTS: + fmt = AFMT_S16_LE; + return IOCTL_OUT(arg, fmt); + case SNDCTL_DSP_GETBLKSIZE: + return IOCTL_OUT(arg, audio_fragsize); + case SNDCTL_DSP_SUBDIVIDE: + break; + case SNDCTL_DSP_SETFRAGMENT: +/* if (output_stream.buffers) { + return -EBUSY; + } + get_user(val, (long *) arg); + audio_fragsize = 1 << (val & 0xFFFF); + if (audio_fragsize < 256) + audio_fragsize = 256; + if (audio_fragsize > 16384) + audio_fragsize = 16384; + audio_nbfrags = (val >> 16) & 0x7FFF; + if (audio_nbfrags < 2) + audio_nbfrags = 2; + if (audio_nbfrags * audio_fragsize > 128 * 1024) + audio_nbfrags = 128 * 1024 / audio_fragsize; + if (sq_allocate_buffers(&output_stream)) { + return -ENOMEM; + } + return 0; + case SNDCTL_DSP_GETOSPACE: + abinfo.fragsize = audio_fragsize; + abinfo.fragstotal = audio_nbfrags; + abinfo.fragments = lastsent-output_stream.buf_idx; + if (abinfo.fragments<0) + abinfo.fragments += abinfo.fragstotal; + abinfo.bytes = abinfo.fragments*abinfo.fragsize; + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; +*/ + + case SNDCTL_DSP_GETOSPACE: + { + audio_stream_t *s = &output_stream; + audio_buf_info *inf = (audio_buf_info *) arg; + int err = verify_area(VERIFY_WRITE, inf, sizeof(*inf)); + int i; + int frags = 0, bytes = 0; + + if (err) + return err; + if (output_stream.buffers) { + for (i = 0; i < s->nbfrags; i++) { + if (atomic_read(&s->buffers[i].sem.count) > 0) { + if (s->buffers[i].size == 0) frags++; + bytes += s->fragsize - s->buffers[i].size; + } + } + put_user(s->nbfrags, &inf->fragstotal); + put_user(s->fragsize, &inf->fragsize); + } else { + frags=audio_nbfrags; + bytes=frags*audio_fragsize; + put_user(frags, &inf->fragstotal); + put_user(audio_fragsize, &inf->fragsize); + } + put_user(frags, &inf->fragments); + return put_user(bytes, &inf->bytes); + } + + case SNDCTL_DSP_GETISPACE: + { + audio_stream_t *s = &input_stream; + audio_buf_info *inf = (audio_buf_info *) arg; + int err = verify_area(VERIFY_WRITE, inf, sizeof(*inf)); + int i; + int frags = 0, bytes = 0; + + if (err) + return err; + if (input_stream.buffers) + for (i = 0; i < s->nbfrags; i++) { + if (atomic_read(&s->buffers[i].sem.count) > 0) { + if (s->buffers[i].size == s->fragsize) frags++; + bytes += s->buffers[i].size; + } + } + else { + frags=0; + bytes=0; + } + put_user(frags, &inf->fragments); + put_user(s->nbfrags, &inf->fragstotal); + put_user(s->fragsize, &inf->fragsize); + return put_user(bytes, &inf->bytes); + } + + default: + ret = mixer_ioctl(inode, file, cmd, arg); + DPRINTK("Returning after mixer_ioctl\n"); + return ret; + } + return -EINVAL; +} + +static struct file_operations sq_fops = +{ + llseek: sound_lseek, + write: sq_write, + read: sq_read, + poll: sq_poll, + ioctl: sq_ioctl, + open: sq_open, + release: sq_release, +}; + + +static void __init sq_init(void) +{ + sq_unit = register_sound_dsp(&sq_fops, -1); + if (sq_unit < 0) { + return; + } + + sound.format = AFMT_S16_LE; + sound.stereo = 0; + sound.speed = 22050; + + CollieSetFormat(sound.format); + Collie_audio_power_off(); + input_stream.buf=input_stream.buffers=output_stream.buf=output_stream.buffers=NULL; +} + + +/*** Common stuff ********************************************************/ + +static long long sound_lseek(struct file *file, long long offset, int orig) +{ + return -ESPIPE; +} + +/*** Power Management ****************************************************/ + +#ifdef CONFIG_PM +static int collie_sound_pm_callback(struct pm_dev *pm_dev, + pm_request_t req, void *data) +{ + switch (req) { + case PM_SUSPEND: + if (audio_refcount == 1) { + sa1100_dma_sleep((dmach_t)COLLIE_BUZZER_DMA_CHANNEL); + sa1100_dma_sleep((dmach_t)COLLIE_BUZZER_DMA_CHANNEL_INPUT); + Collie_audio_power_off(); + } else { + sa1100_dma_sleep((dmach_t)COLLIE_BUZZER_DMA_CHANNEL); + sa1100_dma_sleep((dmach_t)COLLIE_BUZZER_DMA_CHANNEL_INPUT); + } + break; + case PM_RESUME: + Collie_sound_hard_init(); +// Collie_audio_power_off(); + if (audio_refcount == 1) { + Collie_audio_power_on(); + sa1100_dma_wakeup((dmach_t)COLLIE_BUZZER_DMA_CHANNEL); + sa1100_dma_wakeup((dmach_t)COLLIE_BUZZER_DMA_CHANNEL_INPUT); + } else { + sa1100_dma_wakeup((dmach_t)COLLIE_BUZZER_DMA_CHANNEL); + sa1100_dma_wakeup((dmach_t)COLLIE_BUZZER_DMA_CHANNEL_INPUT); + } + break; + } + return 0; +} +#endif + +/*** Config & Setup ******************************************************/ + +int __init Collie_sound_init(void) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)) + ucbstruct = ucb1x00_get(); +#endif + if (!CollieIrqInit()) { + printk("Sound driver: Interrupt initialization failed\n"); + return -1; + } + Ser4MCDR0 = 0; /* ucb1200_sa1100_set_mcdr0(0); */ + + Collie_sound_hard_init(); + + /* Set default settings. */ + sq_init(); + /* Set up /dev/mixer. */ + mixer_init(); +#ifdef MODULE + irq_installed = 1; +#endif + printk("Collie tc35143af Sound Driver Installed\n"); +#ifdef CONFIG_PM + collie_sound_pm_dev = pm_register(PM_SYS_DEV, 0, + collie_sound_pm_callback); +#endif + return 0; +} + +#ifdef MODULE +static int collie_tc35143_init_module(void) +{ + Collie_sound_init(); + sq_allocate_buffers(&output_stream); + sq_allocate_buffers(&input_stream); + return 0; +} + +static void collie_tc35143_cleanup_module(void) +{ +#ifdef CONFIG_PM + pm_unregister(collie_sound_pm_dev); +#endif + if (irq_installed) { + sa1100_free_dma(COLLIE_BUZZER_DMA_CHANNEL); + sa1100_free_dma(COLLIE_BUZZER_DMA_CHANNEL_INPUT); + } + + sq_release_buffers(&output_stream); + sq_release_buffers(&input_stream); + unregister_sound_mixer(mixer_unit); + unregister_sound_special(state_unit); + unregister_sound_dsp(sq_unit); + printk("collie_tc35143af has to go now, see you later!\n"); +} + +module_init(collie_tc35143_init_module); +module_exit(collie_tc35143_cleanup_module); +MODULE_DESCRIPTION("Collie tc35143af 16bit sound driver"); +MODULE_AUTHOR("SHARP"); +MODULE_LICENSE("GPL"); +#endif /* MODULE */ + diff -Nuar linux-2.4.18/drivers/sound/Makefile linux-2.4.18p/drivers/sound/Makefile --- linux-2.4.18/drivers/sound/Makefile 2003-05-13 11:18:36.000000000 +0200 +++ linux-2.4.18p/drivers/sound/Makefile 2004-10-12 23:11:29.000000000 +0200 @@ -11,7 +11,7 @@ msnd.o opl3.o sb_common.o sequencer_syms.o \ sound_core.o sound_syms.o uart401.o \ nm256_audio.o ac97.o ac97_codec.o aci.o \ - sa1100-audio.o pxa-audio.o pxa-ac97.o + sa1100-audio.o pxa-audio.o pxa-ac97.o collie_ssp.o # Each configuration option enables a list of files. @@ -78,7 +78,7 @@ obj-$(CONFIG_SOUND_SA1111_UDA1341) += sa1111-uda1341.o obj-$(CONFIG_SOUND_SA1100SSP) += sa1100ssp.o obj-$(CONFIG_SOUND_COLLIE_SSP) += collie_ssp.o -obj-$(CONFIG_SOUND_COLLIE_TC35143) += collie-tc35143.o +obj-$(CONFIG_SOUND_COLLIE_TC35143) += collie_tc35143af.o obj-$(CONFIG_SOUND_PXA_AC97)+= pxa-ac97.o pxa-audio.o ac97_codec.o obj-$(CONFIG_SOUND_EMU10K1) += ac97_codec.o obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o