From 7c7cae17e04765692aa3d2bda5c771f909219f27 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 6 Apr 2009 14:38:43 -0700 Subject: ALSA: wavefront - Always use request_firmware() Always use request_firmware() for loading yss225_registers image. Signed-off-by: Takashi Iwai Signed-off-by: David Woodhouse --- sound/isa/Kconfig | 10 - sound/isa/wavefront/wavefront_fx.c | 16 - sound/isa/wavefront/yss225.c | 2739 ------------------------------------ 3 files changed, 2765 deletions(-) delete mode 100644 sound/isa/wavefront/yss225.c (limited to 'sound') diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index c5c9a92..c6942a4 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -395,16 +395,6 @@ config SND_WAVEFRONT To compile this driver as a module, choose M here: the module will be called snd-wavefront. -config SND_WAVEFRONT_FIRMWARE_IN_KERNEL - bool "In-kernel firmware for Wavefront" - depends on SND_WAVEFRONT - default y - help - Say Y here to include the static firmware for FX DSP built in - the kernel for the Wavefront driver. If you choose N here, - you need to install the firmware files from the - alsa-firmware package. - config SND_MSND_PINNACLE tristate "Turtle Beach MultiSound Pinnacle/Fiji driver" depends on X86 && EXPERIMENTAL diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index dfc449a..a4345fc 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c @@ -34,14 +34,6 @@ #define WAIT_IDLE 0xff -#ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL -#include "yss225.c" -static const struct firmware yss225_registers_firmware = { - .data = (u8 *)yss225_registers, - .size = sizeof yss225_registers -}; -#endif - static int wavefront_fx_idle (snd_wavefront_t *dev) @@ -260,16 +252,12 @@ snd_wavefront_fx_start (snd_wavefront_t *dev) if (dev->fx_initialized) return 0; -#ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL - firmware = &yss225_registers_firmware; -#else err = request_firmware(&firmware, "yamaha/yss225_registers.bin", dev->card->dev); if (err < 0) { err = -1; goto out; } -#endif for (i = 0; i + 1 < firmware->size; i += 2) { if (firmware->data[i] >= 8 && firmware->data[i] < 16) { @@ -292,12 +280,8 @@ snd_wavefront_fx_start (snd_wavefront_t *dev) err = 0; out: -#ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL release_firmware(firmware); -#endif return err; } -#ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL MODULE_FIRMWARE("yamaha/yss225_registers.bin"); -#endif diff --git a/sound/isa/wavefront/yss225.c b/sound/isa/wavefront/yss225.c deleted file mode 100644 index 9f6be3f..0000000 --- a/sound/isa/wavefront/yss225.c +++ /dev/null @@ -1,2739 +0,0 @@ -/* - * Copyright (c) 1998-2002 by Paul Davis - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* weird stuff, derived from port I/O tracing with dosemu */ - -static const struct { - unsigned char addr; - unsigned char data; -} yss225_registers[] __devinitdata = { -/* Set all bits for all channels on the MOD unit to zero */ -{ WAIT_IDLE }, { 0xe, 0x10 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x11 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x12 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x13 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x14 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x15 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x16 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x17 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x18 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x19 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x20 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x21 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x22 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x23 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x24 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x25 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x26 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x27 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x28 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x29 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x30 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x31 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x32 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x33 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x34 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x35 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x36 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x37 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x38 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x39 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x40 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x41 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x42 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x43 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x44 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x45 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x46 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x47 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x48 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x49 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x50 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x51 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x52 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x53 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x54 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x55 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x56 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x57 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x58 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x59 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x60 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x61 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x62 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x63 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x64 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x65 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x66 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x67 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x68 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x69 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x70 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x71 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x72 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x73 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x74 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x75 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x76 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x77 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x78 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x79 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x80 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x81 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x82 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x83 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x84 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x85 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x86 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x87 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x88 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x89 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x90 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x91 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x92 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x93 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x94 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x95 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x96 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x97 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x98 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x99 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xaa }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xab }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xac }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xad }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xae }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xaf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xba }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbe }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xca }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xce }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xda }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xea }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xeb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xec }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xed }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xee }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xef }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfa }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfe }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xff }, { 0xf, 0x00 }, - -/* XXX But why do this twice? */ -{ WAIT_IDLE }, { 0xe, 0x10 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x11 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x12 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x13 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x14 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x15 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x16 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x17 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x18 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x19 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x20 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x21 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x22 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x23 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x24 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x25 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x26 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x27 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x28 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x29 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x30 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x31 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x32 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x33 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x34 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x35 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x36 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x37 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x38 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x39 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x40 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x41 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x42 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x43 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x44 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x45 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x46 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x47 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x48 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x49 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x50 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x51 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x52 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x53 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x54 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x55 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x56 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x57 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x58 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x59 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x60 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x61 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x62 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x63 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x64 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x65 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x66 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x67 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x68 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x69 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x70 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x71 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x72 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x73 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x74 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x75 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x76 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x77 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x78 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x79 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x80 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x81 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x82 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x83 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x84 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x85 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x86 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x87 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x88 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x89 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x90 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x91 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x92 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x93 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x94 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x95 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x96 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x97 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x98 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x99 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xaa }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xab }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xac }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xad }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xae }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xaf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xba }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbe }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xca }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xce }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xda }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xea }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xeb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xec }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xed }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xee }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xef }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfa }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfe }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xff }, { 0xf, 0x00 }, - -/* mute on */ -{ WAIT_IDLE }, { 0x8, 0x02 }, - -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, - -/* either because of stupidity by TB's programmers, or because it - actually does something, rezero the MOD page. */ -{ WAIT_IDLE }, { 0xe, 0x10 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x11 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x12 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x13 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x14 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x15 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x16 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x17 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x18 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x19 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x1f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x20 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x21 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x22 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x23 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x24 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x25 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x26 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x27 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x28 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x29 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x2f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x30 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x31 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x32 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x33 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x34 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x35 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x36 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x37 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x38 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x39 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x3f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x40 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x41 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x42 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x43 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x44 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x45 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x46 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x47 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x48 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x49 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x4f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x50 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x51 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x52 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x53 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x54 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x55 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x56 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x57 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x58 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x59 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x5f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x60 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x61 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x62 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x63 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x64 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x65 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x66 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x67 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x68 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x69 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x6f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x70 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x71 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x72 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x73 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x74 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x75 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x76 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x77 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x78 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x79 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x7f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x80 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x81 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x82 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x83 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x84 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x85 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x86 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x87 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x88 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x89 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x8f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x90 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x91 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x92 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x93 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x94 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x95 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x96 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x97 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x98 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x99 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9a }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9b }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9c }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9d }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9e }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0x9f }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xa9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xaa }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xab }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xac }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xad }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xae }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xaf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xb9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xba }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbe }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xbf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xc9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xca }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xce }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xcf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xd9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xda }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xe9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xea }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xeb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xec }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xed }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xee }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xef }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf0 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf1 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf2 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf3 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf4 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf5 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf6 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf7 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf8 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xf9 }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfa }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfb }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfc }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfd }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xfe }, { 0xf, 0x00 }, -{ WAIT_IDLE }, { 0xe, 0xff }, { 0xf, 0x00 }, - -/* load page zero */ -{ 0x9, 0x05 }, { 0xb, 0x00 }, { 0xa, 0x00 }, - -{ 0xd, 0x01 }, { 0xc, 0x7c }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1e }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0xf5 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x11 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x32 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x13 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x14 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x76 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x18 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x19 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0x1a }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0x17 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0x80 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x10 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0xa0 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0xd1 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0xf2 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x13 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0xf4 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xe0 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x15 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x16 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x17 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x50 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x71 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x92 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0xb3 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0xa0 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0xd4 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0xf5 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x70 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0xa0 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x11 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x16 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x10 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x17 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1d }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xdf }, { WAIT_IDLE }, - -/* Now load page one */ -{ 0x9, 0x05 }, { 0xb, 0x01 }, { 0xa, 0x00 }, - -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x19 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1f }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0xd8 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x19 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x18 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0xfa }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1a }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x80 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xfb }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xa0 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xd7 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xf7 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1c }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0x3c }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0x3f }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0xdf }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0x5d }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0x7d }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0x9e }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0xbe }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xdb }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xdb }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xe0 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xfb }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xfb }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE }, - -{ 0x9, 0x05 }, { 0xb, 0x02 }, { 0xa, 0x00 }, - -{ 0xc, 0xc4 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x25 }, { WAIT_IDLE }, -{ 0xc, 0x01 }, { WAIT_IDLE }, -{ 0xc, 0x06 }, { WAIT_IDLE }, -{ 0xc, 0xc4 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x25 }, { WAIT_IDLE }, -{ 0xc, 0x01 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x04 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x04 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x05 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x44 }, { WAIT_IDLE }, - -{ 0x9, 0x05 }, { 0xb, 0x03 }, { 0xa, 0x00 }, - -{ 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x47 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x06 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x80 }, { WAIT_IDLE }, -{ 0xc, 0x80 }, { WAIT_IDLE }, -{ 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x70 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x42 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x42 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x42 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x42 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x40 }, { WAIT_IDLE }, - -{ 0x9, 0x05 }, { 0xb, 0x04 }, { 0xa, 0x00 }, - -{ 0xc, 0x63 }, { WAIT_IDLE }, -{ 0xc, 0x03 }, { WAIT_IDLE }, -{ 0xc, 0x26 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x2c }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x24 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x2e }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x01 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x22 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x22 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x22 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x62 }, { WAIT_IDLE }, -{ 0xc, 0x02 }, { WAIT_IDLE }, -{ 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xc, 0x01 }, { WAIT_IDLE }, -{ 0xc, 0x21 }, { WAIT_IDLE }, -{ 0xc, 0x01 }, { WAIT_IDLE }, - -/* Load memory area (page six) */ -{ 0x9, 0x01 }, { 0xb, 0x06 }, - -{ 0xa, 0x00 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x02 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x04 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x06 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x08 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x0a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x0c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x0e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x10 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x12 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x14 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x16 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x18 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x1a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x1c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x1e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x20 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x22 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x24 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x26 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x28 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x2a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x2c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x2e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x30 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x32 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x34 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x36 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x38 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x3a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x3c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x3e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x42 }, { 0xd, 0x03 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x44 }, { 0xd, 0x01 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x46 }, { 0xd, 0x0a }, { 0xc, 0x21 }, { WAIT_IDLE }, -{ 0xa, 0x48 }, { 0xd, 0x0d }, { 0xc, 0x23 }, { WAIT_IDLE }, -{ 0xa, 0x4a }, { 0xd, 0x23 }, { 0xc, 0x1b }, { WAIT_IDLE }, -{ 0xa, 0x4c }, { 0xd, 0x37 }, { 0xc, 0x8f }, { WAIT_IDLE }, -{ 0xa, 0x4e }, { 0xd, 0x45 }, { 0xc, 0x77 }, { WAIT_IDLE }, -{ 0xa, 0x50 }, { 0xd, 0x52 }, { 0xc, 0xe2 }, { WAIT_IDLE }, -{ 0xa, 0x52 }, { 0xd, 0x1c }, { 0xc, 0x92 }, { WAIT_IDLE }, -{ 0xa, 0x54 }, { 0xd, 0x1c }, { 0xc, 0x52 }, { WAIT_IDLE }, -{ 0xa, 0x56 }, { 0xd, 0x07 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x58 }, { 0xd, 0x2f }, { 0xc, 0xc6 }, { WAIT_IDLE }, -{ 0xa, 0x5a }, { 0xd, 0x0b }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x5c }, { 0xd, 0x30 }, { 0xc, 0x06 }, { WAIT_IDLE }, -{ 0xa, 0x5e }, { 0xd, 0x17 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x60 }, { 0xd, 0x3d }, { 0xc, 0xda }, { WAIT_IDLE }, -{ 0xa, 0x62 }, { 0xd, 0x29 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x64 }, { 0xd, 0x3e }, { 0xc, 0x41 }, { WAIT_IDLE }, -{ 0xa, 0x66 }, { 0xd, 0x39 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x68 }, { 0xd, 0x4c }, { 0xc, 0x48 }, { WAIT_IDLE }, -{ 0xa, 0x6a }, { 0xd, 0x49 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x6c }, { 0xd, 0x4c }, { 0xc, 0x6c }, { WAIT_IDLE }, -{ 0xa, 0x6e }, { 0xd, 0x11 }, { 0xc, 0xd2 }, { WAIT_IDLE }, -{ 0xa, 0x70 }, { 0xd, 0x16 }, { 0xc, 0x0c }, { WAIT_IDLE }, -{ 0xa, 0x72 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x74 }, { 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE }, -{ 0xa, 0x76 }, { 0xd, 0x0f }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x78 }, { 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE }, -{ 0xa, 0x7a }, { 0xd, 0x13 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x7c }, { 0xd, 0x80 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x7e }, { 0xd, 0x80 }, { 0xc, 0x80 }, { WAIT_IDLE }, - -{ 0x9, 0x05 }, { 0xb, 0x07 }, { 0xa, 0x00 }, - -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0xe9 }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0x8c }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0x8c }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x1a }, { 0xc, 0x75 }, { WAIT_IDLE }, -{ 0xd, 0x0d }, { 0xc, 0x8b }, { WAIT_IDLE }, -{ 0xd, 0x04 }, { 0xc, 0xe9 }, { WAIT_IDLE }, -{ 0xd, 0x0b }, { 0xc, 0x16 }, { WAIT_IDLE }, -{ 0xd, 0x1a }, { 0xc, 0x38 }, { WAIT_IDLE }, -{ 0xd, 0x0d }, { 0xc, 0xc8 }, { WAIT_IDLE }, -{ 0xd, 0x04 }, { 0xc, 0x6f }, { WAIT_IDLE }, -{ 0xd, 0x0b }, { 0xc, 0x91 }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x8f }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0x62 }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0x62 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x7b }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0x97 }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0x97 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x52 }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0xf6 }, { WAIT_IDLE }, -{ 0xd, 0x06 }, { 0xc, 0xf6 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x19 }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE }, -{ 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE }, -{ 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE }, -{ 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE }, -{ 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE }, -{ 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE }, -{ 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE }, -{ 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, - -/* Now setup the MOD area. */ -{ 0xe, 0x01 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x02 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x03 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x04 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x05 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x06 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x07 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x08 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x09 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0a }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0b }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0c }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0d }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0e }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0f }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, - -{ 0xe, 0xb0 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb1 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb2 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb3 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb4 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb5 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb6 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb7 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb8 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb9 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xba }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xbb }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xbc }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xbd }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xbe }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xbf }, { 0xf, 0x20 }, { WAIT_IDLE }, - -{ 0xe, 0xf0 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf1 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf2 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf3 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf4 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf5 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf6 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf7 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf8 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf9 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xfa }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xfb }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xfc }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xfd }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xfe }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xff }, { 0xf, 0x20 }, { WAIT_IDLE }, - -{ 0xe, 0x10 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x11 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x12 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x13 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x14 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x15 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x16 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x17 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x18 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x19 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x1a }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x1b }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x1c }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x1d }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x1e }, { 0xf, 0x40 }, { WAIT_IDLE }, -{ 0xe, 0x1f }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x20 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x21 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x22 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x23 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x24 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x25 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x26 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x27 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x28 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x29 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x2a }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x2b }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x2c }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x2d }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x2e }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x2f }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x30 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x31 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x32 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x33 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x34 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x35 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x36 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x37 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x38 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x39 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x3a }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x3b }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x3c }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x3d }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x3e }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x3f }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0x40 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x41 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x42 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x43 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x44 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x45 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x46 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x47 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x48 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x49 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x4a }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x4b }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x4c }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x4d }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x4e }, { 0xf, 0x0e }, { WAIT_IDLE }, -{ 0xe, 0x4f }, { 0xf, 0x0e }, { WAIT_IDLE }, -{ 0xe, 0x50 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x51 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x52 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x53 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x54 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x55 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x56 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x57 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x58 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x59 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x5a }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x5b }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x5c }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x5d }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x5e }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x5f }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x60 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x61 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x62 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x63 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x64 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x65 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x66 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x67 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x68 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x69 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x6a }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x6b }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x6c }, { 0xf, 0x40 }, { WAIT_IDLE }, -{ 0xe, 0x6d }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x6e }, { 0xf, 0x40 }, { WAIT_IDLE }, -{ 0xe, 0x6f }, { 0xf, 0x40 }, { WAIT_IDLE }, -{ 0xe, 0x70 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x71 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x72 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x73 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x74 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x75 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x76 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x77 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x78 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x79 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x7a }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x7b }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x7c }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x7d }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x7e }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x7f }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x80 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x81 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x82 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x83 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x84 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x85 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x86 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x87 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x88 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x89 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x8a }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x8b }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x8c }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x8d }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x8e }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x8f }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x90 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x91 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x92 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x93 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x94 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x95 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x96 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x97 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x98 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x99 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x9a }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x9b }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x9c }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x9d }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x9e }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x9f }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa0 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa1 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa2 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa3 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa4 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa5 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa6 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa7 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa8 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa9 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xaa }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xab }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xac }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xad }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xae }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xaf }, { 0xf, 0x00 }, { WAIT_IDLE }, - -{ 0xe, 0xc0 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc1 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc2 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc3 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc4 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc5 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc6 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc7 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc8 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc9 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xca }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xcb }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xcc }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xcd }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xce }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xcf }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd0 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd1 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd2 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd3 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd4 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd5 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd6 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd7 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd8 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd9 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xda }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xdb }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xdc }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xdd }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xde }, { 0xf, 0x10 }, { WAIT_IDLE }, -{ 0xe, 0xdf }, { 0xf, 0x10 }, { WAIT_IDLE }, -{ 0xe, 0xe0 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe1 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe2 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe3 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe4 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe5 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe6 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe7 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe8 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe9 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xea }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xeb }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xec }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xed }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xee }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xef }, { 0xf, 0x00 }, { WAIT_IDLE }, - -{ 0xe, 0x01 }, { 0xf, 0x00 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x01 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x02 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x03 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x04 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x05 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x06 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x07 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x08 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x09 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0a }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0b }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0c }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0d }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0e }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x0f }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, - -/* mute on */ -{ 0x8, 0x02 }, - -/* Now set the coefficients and so forth for the programs above */ -{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x00 }, { 0xa, 0x4b }, { 0xd, 0x03 }, { 0xc, 0x11 }, { WAIT_IDLE }, -{ 0xb, 0x00 }, { 0xa, 0x4d }, { 0xd, 0x01 }, { 0xc, 0x32 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x01 }, { 0xa, 0x40 }, { 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xb, 0x01 }, { 0xa, 0x41 }, { 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x00 }, { 0xa, 0x47 }, { 0xd, 0x01 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x00 }, { 0xa, 0x4a }, { 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x00 }, { 0xa, 0x00 }, { 0xd, 0x01 }, { 0xc, 0x1c }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x00 }, { 0xa, 0x44 }, { 0xd, 0x01 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x00 }, { 0xa, 0x42 }, { 0xd, 0x01 }, { 0xc, 0x1a }, { WAIT_IDLE }, -{ 0xb, 0x00 }, { 0xa, 0x43 }, { 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x01 }, { 0xa, 0x40 }, { 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xb, 0x01 }, { 0xa, 0x41 }, { 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x51 }, { 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x50 }, { 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x4f }, { 0xd, 0x03 }, { 0xc, 0x81 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x53 }, { 0xd, 0x1a }, { 0xc, 0x76 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x54 }, { 0xd, 0x0d }, { 0xc, 0x8b }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x55 }, { 0xd, 0x04 }, { 0xc, 0xe9 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x56 }, { 0xd, 0x0b }, { 0xc, 0x17 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x57 }, { 0xd, 0x1a }, { 0xc, 0x38 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x58 }, { 0xd, 0x0d }, { 0xc, 0xc9 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x59 }, { 0xd, 0x04 }, { 0xc, 0x6f }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x5a }, { 0xd, 0x0b }, { 0xc, 0x91 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x73 }, { 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x74 }, { 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x75 }, { 0xd, 0x04 }, { 0xc, 0xd9 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x76 }, { 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x77 }, { 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x78 }, { 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x79 }, { 0xd, 0x04 }, { 0xc, 0xd9 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x7a }, { 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x5e }, { 0xd, 0x03 }, { 0xc, 0x68 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x5c }, { 0xd, 0x04 }, { 0xc, 0x31 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x5d }, { 0xd, 0x04 }, { 0xc, 0x31 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x62 }, { 0xd, 0x03 }, { 0xc, 0x52 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x60 }, { 0xd, 0x04 }, { 0xc, 0x76 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x61 }, { 0xd, 0x04 }, { 0xc, 0x76 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x66 }, { 0xd, 0x03 }, { 0xc, 0x2e }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x64 }, { 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x65 }, { 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x6a }, { 0xd, 0x02 }, { 0xc, 0xf6 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x68 }, { 0xd, 0x05 }, { 0xc, 0x62 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x69 }, { 0xd, 0x05 }, { 0xc, 0x62 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x46 }, { 0xd, 0x0a }, { 0xc, 0x22 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x48 }, { 0xd, 0x0d }, { 0xc, 0x24 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x6e }, { 0xd, 0x11 }, { 0xc, 0xd3 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x70 }, { 0xd, 0x15 }, { 0xc, 0xcb }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x52 }, { 0xd, 0x20 }, { 0xc, 0x93 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x54 }, { 0xd, 0x20 }, { 0xc, 0x54 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x4a }, { 0xd, 0x27 }, { 0xc, 0x1d }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x58 }, { 0xd, 0x2f }, { 0xc, 0xc8 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x5c }, { 0xd, 0x30 }, { 0xc, 0x07 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x4c }, { 0xd, 0x37 }, { 0xc, 0x90 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x60 }, { 0xd, 0x3d }, { 0xc, 0xdb }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x64 }, { 0xd, 0x3e }, { 0xc, 0x42 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x4e }, { 0xd, 0x45 }, { 0xc, 0x78 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x68 }, { 0xd, 0x4c }, { 0xc, 0x48 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x6c }, { 0xd, 0x4c }, { 0xc, 0x6c }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x50 }, { 0xd, 0x52 }, { 0xc, 0xe2 }, { WAIT_IDLE }, -{ 0xb, 0x06 }, { 0xa, 0x42 }, { 0xd, 0x02 }, { 0xc, 0xba }, { WAIT_IDLE }, - -/* Some settings (?) */ -{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x14 }, -{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x20 }, -{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x20 }, - -/* some more coefficients */ -{ WAIT_IDLE }, { 0xb, 0x06 }, { 0xa, 0x78 }, { 0xd, 0x00 }, { 0xc, 0x40 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x03 }, { 0xd, 0x0f }, { 0xc, 0xff }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x0b }, { 0xd, 0x0f }, { 0xc, 0xff }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x02 }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x0a }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, - -/* Now, for some strange reason, lets reload every page - and all the coefficients over again. I have *NO* idea - why this is done. I do know that no sound is produced - is this phase is omitted. */ -{ 0x9, 0x05 }, { 0xb, 0x00 }, { 0xa, 0x10 }, - -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, - -{ 0x9, 0x05 }, { 0xb, 0x01 }, { 0xa, 0x10 }, - -{ 0xd, 0x01 }, { 0xc, 0xc0 }, { WAIT_IDLE }, -{ 0xd, 0x01 }, { 0xc, 0xfa }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x1a }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, - -{ WAIT_IDLE }, { WAIT_IDLE }, - -{ 0x9, 0x05 }, { 0xb, 0x02 }, { 0xa, 0x10 }, - -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x46 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, - -{ 0x9, 0x05 }, { 0xb, 0x03 }, { 0xa, 0x10 }, - -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, - -{ 0x9, 0x05 }, { 0xb, 0x04 }, { 0xa, 0x10 }, - -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xc, 0x00 }, { WAIT_IDLE }, - -/* Page six v.2 */ -{ 0x9, 0x01 }, { 0xb, 0x06 }, - -{ 0xa, 0x10 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x12 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x14 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x16 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x18 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x1a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x1c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x1e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x20 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x22 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x24 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x26 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x28 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x2a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x2c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x2e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x30 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x32 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x34 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x36 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x38 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x3a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x3c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xa, 0x3e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, - -{ 0x9, 0x05 }, { 0xb, 0x07 }, { 0xa, 0x10 }, - -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, - -{ 0xe, 0x01 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x02 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x03 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x04 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x05 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x06 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x07 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xb0 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb1 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb2 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb3 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb4 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb5 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb6 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xb7 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf0 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf1 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf2 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf3 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf4 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf5 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf6 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0xf7 }, { 0xf, 0x20 }, { WAIT_IDLE }, -{ 0xe, 0x10 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x11 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x12 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x13 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x14 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x15 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x16 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x17 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x20 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x21 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x22 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x23 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x24 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x25 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x26 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x27 }, { 0xf, 0xff }, { WAIT_IDLE }, -{ 0xe, 0x30 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x31 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x32 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x33 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x34 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x35 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x36 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x37 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x40 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x41 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x42 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x43 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x44 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x45 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x46 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x47 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x50 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x51 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x52 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x53 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x54 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x55 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x56 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x57 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x60 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x61 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x62 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x63 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x64 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x65 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x66 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x67 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x70 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x71 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x72 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x73 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x74 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x75 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x76 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x77 }, { 0xf, 0xc0 }, { WAIT_IDLE }, -{ 0xe, 0x80 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x81 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x82 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x83 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x84 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x85 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x86 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x87 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x90 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x91 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x92 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x93 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x94 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x95 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x96 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x97 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa0 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa1 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa2 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa3 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa4 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa5 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa6 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xa7 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc0 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc1 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc2 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc3 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc4 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc5 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc6 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xc7 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd0 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd1 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd2 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd3 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd4 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd5 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd6 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xd7 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe0 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe1 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe2 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe3 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe4 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe5 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe6 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0xe7 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x00 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x02 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x03 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x04 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x05 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x06 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, -{ 0xe, 0x01 }, { 0xf, 0x07 }, { WAIT_IDLE }, -{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE }, - -{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x45 }, { 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x48 }, { 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x7b }, { 0xd, 0x04 }, { 0xc, 0xcc }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x7d }, { 0xd, 0x04 }, { 0xc, 0xcc }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE }, - -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x00 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x28 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x28 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x51 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x51 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x7a }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x7a }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0xa3 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0xa3 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0xcc }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0xcc }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0xf5 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0xf5 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x1e }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x1e }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x47 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x47 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x70 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x70 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x99 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x99 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0xc2 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0xc2 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0xeb }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0xeb }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x14 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x14 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x3d }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x3d }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x66 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x66 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x8f }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x8f }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0xb8 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0xb8 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0xe1 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0xe1 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x0a }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x0a }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x33 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x33 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x5c }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x5c }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x85 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x85 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0xae }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0xae }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0xd7 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0xd7 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x00 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x00 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x28 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x28 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x51 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x51 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x7a }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x7a }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0xa3 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0xa3 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0xcc }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0xcc }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0xf5 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0xf5 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x1e }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x1e }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x47 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x47 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x70 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x70 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x99 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x99 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0xc2 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0xc2 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0xeb }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0xeb }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x14 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x14 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x3d }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x3d }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x66 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x66 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x8f }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x8f }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0xb8 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0xb8 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0xe1 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0xe1 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x0a }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x0a }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x33 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x33 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x5c }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x5c }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x85 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x85 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0xae }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0xae }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0xd7 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0xd7 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x00 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x00 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x28 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x28 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x51 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x51 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x7a }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x7a }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0xa3 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0xa3 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0xcc }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0xcc }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0xf5 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0xf5 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x1e }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x1e }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x47 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x47 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x70 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x70 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x99 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x99 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0xc2 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0xc2 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0xeb }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0xeb }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x14 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x14 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x3d }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x3d }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x66 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x66 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x8f }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x8f }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0xb8 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0xb8 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0xe1 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0xe1 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x0a }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x0a }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x33 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x33 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x5c }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x5c }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x85 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x85 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0xae }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0xae }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0xd7 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0xd7 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x00 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x00 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x28 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x28 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x51 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x51 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x7a }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x7a }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0xa3 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0xa3 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0xcc }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0xcc }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0xf5 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0xf5 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x1e }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x1e }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x47 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x47 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x70 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x70 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x99 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x99 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0xc2 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0xc2 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0xeb }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0xeb }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x14 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x14 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x3d }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x3d }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x66 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x66 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x8f }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x8f }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0xb8 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0xb8 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0xe1 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0xe1 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x0a }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x0a }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x33 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x33 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x5c }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x5c }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x85 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x85 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0xae }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0xae }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0xd7 }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0xd7 }, -{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0xff }, -{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0xff }, - -/* mute off */ -{ 0x8, 0x00 }, { WAIT_IDLE } -}; -- cgit v1.1 From 7816238a539bf56311f04e7ff17076f66d5c902a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 7 Apr 2009 00:45:51 -0700 Subject: sparc: Fix section mismatch warnings in cs4231 sound driver. Signed-off-by: David S. Miller --- sound/sparc/cs4231.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 7d93fa7..8d13d93 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -703,7 +703,7 @@ static int snd_cs4231_timer_stop(struct snd_timer *timer) return 0; } -static void __init snd_cs4231_init(struct snd_cs4231 *chip) +static void __devinit snd_cs4231_init(struct snd_cs4231 *chip) { unsigned long flags; @@ -1020,7 +1020,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer( return bytes_to_frames(substream->runtime, ptr); } -static int __init snd_cs4231_probe(struct snd_cs4231 *chip) +static int __devinit snd_cs4231_probe(struct snd_cs4231 *chip) { unsigned long flags; int i; @@ -1219,7 +1219,7 @@ static struct snd_pcm_ops snd_cs4231_capture_ops = { .pointer = snd_cs4231_capture_pointer, }; -static int __init snd_cs4231_pcm(struct snd_card *card) +static int __devinit snd_cs4231_pcm(struct snd_card *card) { struct snd_cs4231 *chip = card->private_data; struct snd_pcm *pcm; @@ -1248,7 +1248,7 @@ static int __init snd_cs4231_pcm(struct snd_card *card) return 0; } -static int __init snd_cs4231_timer(struct snd_card *card) +static int __devinit snd_cs4231_timer(struct snd_card *card) { struct snd_cs4231 *chip = card->private_data; struct snd_timer *timer; @@ -1499,7 +1499,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, .private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \ ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) } -static struct snd_kcontrol_new snd_cs4231_controls[] __initdata = { +static struct snd_kcontrol_new snd_cs4231_controls[] __devinitdata = { CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, @@ -1538,7 +1538,7 @@ CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1), CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1) }; -static int __init snd_cs4231_mixer(struct snd_card *card) +static int __devinit snd_cs4231_mixer(struct snd_card *card) { struct snd_cs4231 *chip = card->private_data; int err, idx; @@ -1559,7 +1559,7 @@ static int __init snd_cs4231_mixer(struct snd_card *card) static int dev; -static int __init cs4231_attach_begin(struct snd_card **rcard) +static int __devinit cs4231_attach_begin(struct snd_card **rcard) { struct snd_card *card; struct snd_cs4231 *chip; @@ -1590,7 +1590,7 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) return 0; } -static int __init cs4231_attach_finish(struct snd_card *card) +static int __devinit cs4231_attach_finish(struct snd_card *card) { struct snd_cs4231 *chip = card->private_data; int err; @@ -1794,9 +1794,9 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = { .dev_free = snd_cs4231_sbus_dev_free, }; -static int __init snd_cs4231_sbus_create(struct snd_card *card, - struct of_device *op, - int dev) +static int __devinit snd_cs4231_sbus_create(struct snd_card *card, + struct of_device *op, + int dev) { struct snd_cs4231 *chip = card->private_data; int err; @@ -1960,9 +1960,9 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = { .dev_free = snd_cs4231_ebus_dev_free, }; -static int __init snd_cs4231_ebus_create(struct snd_card *card, - struct of_device *op, - int dev) +static int __devinit snd_cs4231_ebus_create(struct snd_card *card, + struct of_device *op, + int dev) { struct snd_cs4231 *chip = card->private_data; int err; -- cgit v1.1 From fa00e046b41663cbda9b1affc0594669e5f14219 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 10 Apr 2009 12:20:45 +0200 Subject: [ALSA] hda_intel: fix unexpected ring buffer positions I found two issues with ICH7-M (it should be related to other HDA chipsets as well): - the ring buffer position is not reset when stream restarts (after xrun) - solved by moving azx_stream_reset() call from open() to prepare() callback and reset posbuf to zero (it might be filled with hw later than position() callback is called) - irq_ignore flag should be set also when ring buffer memory area is not changed in prepare() callback - this patch replaces irq_ignore with more universal check based on jiffies clock Signed-off-by: Jaroslav Kysela --- sound/pci/hda/hda_intel.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 30829ee..6d3b927 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -312,6 +312,9 @@ struct azx_dev { unsigned int period_bytes; /* size of the period in bytes */ unsigned int frags; /* number for period in the play buffer */ unsigned int fifo_size; /* FIFO size */ + unsigned int start_flag: 1; /* stream full start flag */ + unsigned long start_jiffies; /* start + minimum jiffies */ + unsigned long min_jiffies; /* minimum jiffies before position is valid */ void __iomem *sd_addr; /* stream descriptor pointer */ @@ -330,7 +333,6 @@ struct azx_dev { unsigned int opened :1; unsigned int running :1; unsigned int irq_pending :1; - unsigned int irq_ignore :1; /* * For VIA: * A flag to ensure DMA position is 0 @@ -975,7 +977,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) struct azx *chip = dev_id; struct azx_dev *azx_dev; u32 status; - int i; + int i, ok; spin_lock(&chip->reg_lock); @@ -991,18 +993,14 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); if (!azx_dev->substream || !azx_dev->running) continue; - /* ignore the first dummy IRQ (due to pos_adj) */ - if (azx_dev->irq_ignore) { - azx_dev->irq_ignore = 0; - continue; - } /* check whether this IRQ is really acceptable */ - if (azx_position_ok(chip, azx_dev)) { + ok = azx_position_ok(chip, azx_dev); + if (ok == 1) { azx_dev->irq_pending = 0; spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(azx_dev->substream); spin_lock(&chip->reg_lock); - } else if (chip->bus && chip->bus->workq) { + } else if (ok == 0 && chip->bus && chip->bus->workq) { /* bogus IRQ, process it later */ azx_dev->irq_pending = 1; queue_work(chip->bus->workq, @@ -1088,7 +1086,6 @@ static int azx_setup_periods(struct azx *chip, bdl = (u32 *)azx_dev->bdl.area; ofs = 0; azx_dev->frags = 0; - azx_dev->irq_ignore = 0; pos_adj = bdl_pos_adj[chip->dev_index]; if (pos_adj > 0) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -1109,7 +1106,6 @@ static int azx_setup_periods(struct azx *chip, &bdl, ofs, pos_adj, 1); if (ofs < 0) goto error; - azx_dev->irq_ignore = 1; } } else pos_adj = 0; @@ -1155,6 +1151,9 @@ static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) && --timeout) ; + + /* reset first position - may not be synced with hw at this time */ + *azx_dev->posbuf = 0; } /* @@ -1409,7 +1408,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); mutex_unlock(&chip->open_mutex); - azx_stream_reset(chip, azx_dev); return 0; } @@ -1474,6 +1472,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) unsigned int bufsize, period_bytes, format_val; int err; + azx_stream_reset(chip, azx_dev); format_val = snd_hda_calc_stream_format(runtime->rate, runtime->channels, runtime->format, @@ -1502,6 +1501,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) return err; } + azx_dev->min_jiffies = (runtime->period_size * HZ) / + (runtime->rate * 2); azx_setup_controller(chip, azx_dev); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; @@ -1518,13 +1519,14 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct azx *chip = apcm->chip; struct azx_dev *azx_dev; struct snd_pcm_substream *s; - int start, nsync = 0, sbits = 0; + int rstart = 0, start, nsync = 0, sbits = 0; int nwait, timeout; switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + rstart = 1; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_START: start = 1; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -1554,6 +1556,10 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) if (s->pcm->card != substream->pcm->card) continue; azx_dev = get_azx_dev(s); + if (rstart) { + azx_dev->start_flag = 1; + azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies; + } if (start) azx_stream_start(chip, azx_dev); else @@ -1703,6 +1709,11 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) { unsigned int pos; + if (azx_dev->start_flag && + time_before_eq(jiffies, azx_dev->start_jiffies)) + return -1; /* bogus (too early) interrupt */ + azx_dev->start_flag = 0; + pos = azx_get_position(chip, azx_dev); if (chip->position_fix == POS_FIX_AUTO) { if (!pos) { -- cgit v1.1 From bbf6ad1399e9516b0a95de3ad58ffbaed670e4cc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 10 Apr 2009 12:28:58 +0200 Subject: [ALSA] pcm-midlevel: Add more strict buffer position checks based on jiffies Some drivers like Intel8x0 or Intel HDA are broken for some hardware variants. This patch adds more strict buffer position checks based on jiffies when internal hw_ptr is updated. Enable xrun_debug to see mangling of wrong positions. As a side effect, the hw_ptr interrupt update routine might do slightly better job when many interrupts are lost. Signed-off-by: Jaroslav Kysela --- sound/core/pcm_lib.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index fbb2e39..63d088f 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -209,9 +209,11 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t pos; - snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base; - snd_pcm_sframes_t delta; + snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interrupt, hw_base; + snd_pcm_sframes_t hdelta, delta; + unsigned long jdelta; + old_hw_ptr = runtime->status->hw_ptr; pos = snd_pcm_update_hw_ptr_pos(substream, runtime); if (pos == SNDRV_PCM_POS_XRUN) { xrun(substream); @@ -247,7 +249,30 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) new_hw_ptr = hw_base + pos; } } - if (delta > runtime->period_size) { + hdelta = new_hw_ptr - old_hw_ptr; + jdelta = jiffies - runtime->hw_ptr_jiffies; + if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { + delta = jdelta / + (((runtime->period_size * HZ) / runtime->rate) + + HZ/100); + hw_ptr_error(substream, + "hw_ptr skipping! [Q] " + "(pos=%ld, delta=%ld, period=%ld, " + "jdelta=%lu/%lu/%lu)\n", + (long)pos, (long)hdelta, + (long)runtime->period_size, jdelta, + ((hdelta * HZ) / runtime->rate), delta); + hw_ptr_interrupt = runtime->hw_ptr_interrupt + + runtime->period_size * delta; + if (hw_ptr_interrupt >= runtime->boundary) + hw_ptr_interrupt -= runtime->boundary; + /* rebase to interrupt position */ + hw_base = new_hw_ptr = hw_ptr_interrupt; + /* align hw_base to buffer_size */ + hw_base -= hw_base % runtime->buffer_size; + delta = 0; + } + if (delta > runtime->period_size + runtime->period_size / 2) { hw_ptr_error(substream, "Lost interrupts? " "(stream=%i, delta=%ld, intr_ptr=%ld)\n", @@ -263,6 +288,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; + runtime->hw_ptr_jiffies = jiffies; runtime->hw_ptr_interrupt = hw_ptr_interrupt; return snd_pcm_update_hw_ptr_post(substream, runtime); @@ -275,6 +301,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) snd_pcm_uframes_t pos; snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base; snd_pcm_sframes_t delta; + unsigned long jdelta; old_hw_ptr = runtime->status->hw_ptr; pos = snd_pcm_update_hw_ptr_pos(substream, runtime); @@ -286,14 +313,15 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) new_hw_ptr = hw_base + pos; delta = new_hw_ptr - old_hw_ptr; + jdelta = jiffies - runtime->hw_ptr_jiffies; if (delta < 0) { delta += runtime->buffer_size; if (delta < 0) { hw_ptr_error(substream, "Unexpected hw_pointer value [2] " - "(stream=%i, pos=%ld, old_ptr=%ld)\n", + "(stream=%i, pos=%ld, old_ptr=%ld, jdelta=%li)\n", substream->stream, (long)pos, - (long)old_hw_ptr); + (long)old_hw_ptr, jdelta); return 0; } hw_base += runtime->buffer_size; @@ -301,12 +329,13 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) hw_base = 0; new_hw_ptr = hw_base + pos; } - if (delta > runtime->period_size && runtime->periods > 1) { + if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) { hw_ptr_error(substream, "hw_ptr skipping! " - "(pos=%ld, delta=%ld, period=%ld)\n", + "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n", (long)pos, (long)delta, - (long)runtime->period_size); + (long)runtime->period_size, jdelta, + ((delta * HZ) / runtime->rate)); return 0; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && @@ -315,6 +344,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) runtime->hw_ptr_base = hw_base; runtime->status->hw_ptr = new_hw_ptr; + runtime->hw_ptr_jiffies = jiffies; return snd_pcm_update_hw_ptr_post(substream, runtime); } @@ -1441,6 +1471,7 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, runtime->status->hw_ptr %= runtime->buffer_size; else runtime->status->hw_ptr = 0; + runtime->hw_ptr_jiffies = jiffies; snd_pcm_stream_unlock_irqrestore(substream, flags); return 0; } -- cgit v1.1 From 920e4ae31cb113328e617f4a0663fb17d7b09124 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 13 Apr 2009 20:45:42 +0200 Subject: [ALSA] intel8x0: an attempt to make ac97_clock measurement more reliable - use monotonic posix clock to measure time - try to avoid reading zero from PICB (position in current buffer) register - show also measured samples - when clock is near 41000 or 44100, use exactly these values (they appears to be reference clocks for hardware manufacturers) Signed-off-by: Jaroslav Kysela --- sound/pci/intel8x0.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 5764881..c86ff49 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2661,8 +2661,9 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) struct snd_pcm_substream *subs; struct ichdev *ichdev; unsigned long port; - unsigned long pos, t; - struct timeval start_time, stop_time; + unsigned long pos, pos1, t; + int civ, timeout = 1000; + struct timespec start_time, stop_time; if (chip->ac97_bus->clock != 48000) return; /* specified in module option */ @@ -2693,16 +2694,27 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE); iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot); } - do_gettimeofday(&start_time); + do_posix_clock_monotonic_gettime(&start_time); spin_unlock_irq(&chip->reg_lock); msleep(50); spin_lock_irq(&chip->reg_lock); /* check the position */ + do { + civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV); + pos1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb); + if (pos1 == 0) { + udelay(10); + continue; + } + if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) && + pos1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) + break; + } while (timeout--); pos = ichdev->fragsize1; - pos -= igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift; + pos -= pos1 << ichdev->pos_shift; pos += ichdev->position; chip->in_measurement = 0; - do_gettimeofday(&stop_time); + do_posix_clock_monotonic_gettime(&stop_time); /* stop */ if (chip->device_type == DEVICE_ALI) { iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16)); @@ -2717,19 +2729,26 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS); spin_unlock_irq(&chip->reg_lock); + pos /= 4; t = stop_time.tv_sec - start_time.tv_sec; t *= 1000000; - t += stop_time.tv_usec - start_time.tv_usec; - printk(KERN_INFO "%s: measured %lu usecs\n", __func__, t); + t += (stop_time.tv_nsec - start_time.tv_nsec) / 1000; + printk(KERN_INFO "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos); if (t == 0) { - snd_printk(KERN_ERR "?? calculation error..\n"); + snd_printk(KERN_ERR "intel8x0: ?? calculation error..\n"); return; } - pos = (pos / 4) * 1000; + pos *= 1000; pos = (pos / t) * 1000 + ((pos % t) * 1000) / t; if (pos < 40000 || pos >= 60000) /* abnormal value. hw problem? */ printk(KERN_INFO "intel8x0: measured clock %ld rejected\n", pos); + else if (pos > 40500 || pos < 41500) + /* first exception - 41000Hz reference clock */ + chip->ac97_bus->clock = 41000; + else if (pos > 43600 || pos < 44600) + /* second exception - 44100HZ reference clock */ + chip->ac97_bus->clock = 44100; else if (pos < 47500 || pos > 48500) /* not 48000Hz, tuning the clock.. */ chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos; -- cgit v1.1 From da2436a23c038055b1da6fe30b6ea2886b1e07b0 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 13 Apr 2009 21:31:25 +0200 Subject: [ALSA] intel8x0: do not use zero value from PICB register It seems that the zero value from the PICB (position in current buffer) register is not reliable. Use jiffies to correct returned value from the ring buffer pointer callback. Signed-off-by: Jaroslav Kysela --- sound/pci/intel8x0.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index c86ff49..6962f94 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -355,6 +355,9 @@ struct ichdev { unsigned int fragsize1; unsigned int position; unsigned int pos_shift; + unsigned int last_pos; + unsigned long last_pos_jiffies; + unsigned int jiffy_to_bytes; int frags; int lvi; int lvi_frag; @@ -838,7 +841,10 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd ichdev->suspended = 0; /* fallthru */ case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: val = ICH_IOCE | ICH_STARTBM; + ichdev->last_pos = ichdev->position; + ichdev->last_pos_jiffies = jiffies; break; case SNDRV_PCM_TRIGGER_SUSPEND: ichdev->suspended = 1; @@ -849,9 +855,6 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd case SNDRV_PCM_TRIGGER_PAUSE_PUSH: val = ICH_IOCE; break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - val = ICH_IOCE | ICH_STARTBM; - break; default: return -EINVAL; } @@ -1045,6 +1048,7 @@ static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream) ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1; } snd_intel8x0_setup_periods(chip, ichdev); + ichdev->jiffy_to_bytes = (runtime->rate * 4 * ichdev->pos_shift) / HZ; return 0; } @@ -1053,7 +1057,7 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs struct intel8x0 *chip = snd_pcm_substream_chip(substream); struct ichdev *ichdev = get_ichdev(substream); size_t ptr1, ptr; - int civ, timeout = 100; + int civ, timeout = 10; unsigned int position; spin_lock(&chip->reg_lock); @@ -1069,9 +1073,19 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) break; } while (timeout--); - ptr1 <<= ichdev->pos_shift; - ptr = ichdev->fragsize1 - ptr1; - ptr += position; + if (ptr1 != 0) { + ptr1 <<= ichdev->pos_shift; + ptr = ichdev->fragsize1 - ptr1; + ptr += position; + ichdev->last_pos = ptr; + ichdev->last_pos_jiffies = jiffies; + } else { + ptr1 = jiffies - ichdev->last_pos_jiffies; + if (ptr1) + ptr1 -= 1; + ptr = ichdev->last_pos + ptr1 * ichdev->jiffy_to_bytes; + ptr %= ichdev->size; + } spin_unlock(&chip->reg_lock); if (ptr >= ichdev->size) return 0; @@ -2710,9 +2724,13 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) pos1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) break; } while (timeout--); - pos = ichdev->fragsize1; - pos -= pos1 << ichdev->pos_shift; - pos += ichdev->position; + if (pos1 == 0) { /* oops, this value is not reliable */ + pos = 0; + } else { + pos = ichdev->fragsize1; + pos -= pos1 << ichdev->pos_shift; + pos += ichdev->position; + } chip->in_measurement = 0; do_posix_clock_monotonic_gettime(&stop_time); /* stop */ @@ -2729,6 +2747,11 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS); spin_unlock_irq(&chip->reg_lock); + if (pos == 0) { + snd_printk(KERN_ERR "intel8x0: measure - unreliable DMA position..\n"); + return; + } + pos /= 4; t = stop_time.tv_sec - start_time.tv_sec; t *= 1000000; -- cgit v1.1 From e930438c42e744ef1f8bfdbb338253c9f384df42 Mon Sep 17 00:00:00 2001 From: Yang Hongyang Date: Mon, 13 Apr 2009 14:40:14 -0700 Subject: Replace all DMA_nBIT_MASK macro with DMA_BIT_MASK(n) This is the second go through of the old DMA_nBIT_MASK macro,and there're not so many of them left,so I put them into one patch.I hope this is the last round. After this the definition of the old DMA_nBIT_MASK macro could be removed. Signed-off-by: Yang Hongyang Cc: Russell King Cc: Tony Lindgren Cc: "David S. Miller" Cc: James Bottomley Cc: Greg KH Cc: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/pci/hda/hda_intel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 30829ee..7ba8db5 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2260,11 +2260,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, gcap &= ~0x01; /* allow 64bit DMA address if supported by H/W */ - if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK)) - pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK); + if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) + pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); else { - pci_set_dma_mask(pci, DMA_32BIT_MASK); - pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK); + pci_set_dma_mask(pci, DMA_BIT_MASK(32)); + pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)); } /* read number of streams from GCAP register instead of using -- cgit v1.1 From ef44a1ec6eeef189998f84e7230e1d3535b01074 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 10 Apr 2009 09:43:08 +0800 Subject: ALSA: sound/core: use memdup_user() Remove open-coded memdup_user(). Signed-off-by: Li Zefan Signed-off-by: Takashi Iwai --- sound/core/control.c | 35 +++++++---------- sound/core/pcm_compat.c | 11 ++---- sound/core/pcm_native.c | 93 +++++++++++++++++---------------------------- sound/core/seq/seq_compat.c | 9 ++--- sound/core/timer.c | 11 ++---- 5 files changed, 60 insertions(+), 99 deletions(-) (limited to 'sound') diff --git a/sound/core/control.c b/sound/core/control.c index 4b20fa2..17b8d47 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -723,14 +723,11 @@ static int snd_ctl_elem_read_user(struct snd_card *card, { struct snd_ctl_elem_value *control; int result; - - control = kmalloc(sizeof(*control), GFP_KERNEL); - if (control == NULL) - return -ENOMEM; - if (copy_from_user(control, _control, sizeof(*control))) { - kfree(control); - return -EFAULT; - } + + control = memdup_user(_control, sizeof(*control)); + if (IS_ERR(control)) + return PTR_ERR(control); + snd_power_lock(card); result = snd_power_wait(card, SNDRV_CTL_POWER_D0); if (result >= 0) @@ -784,13 +781,10 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file, struct snd_card *card; int result; - control = kmalloc(sizeof(*control), GFP_KERNEL); - if (control == NULL) - return -ENOMEM; - if (copy_from_user(control, _control, sizeof(*control))) { - kfree(control); - return -EFAULT; - } + control = memdup_user(_control, sizeof(*control)); + if (IS_ERR(control)) + return PTR_ERR(control); + card = file->card; snd_power_lock(card); result = snd_power_wait(card, SNDRV_CTL_POWER_D0); @@ -916,13 +910,10 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol, if (op_flag > 0) { if (size > 1024 * 128) /* sane value */ return -EINVAL; - new_data = kmalloc(size, GFP_KERNEL); - if (new_data == NULL) - return -ENOMEM; - if (copy_from_user(new_data, tlv, size)) { - kfree(new_data); - return -EFAULT; - } + + new_data = memdup_user(tlv, size); + if (IS_ERR(new_data)) + return PTR_ERR(new_data); change = ue->tlv_data_size != size; if (!change) change = memcmp(ue->tlv_data, new_data, size); diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 36d7a59..08bfed5 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -232,14 +232,11 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, if (! (runtime = substream->runtime)) return -ENOTTY; - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; /* only fifo_size is different, so just copy all */ - if (copy_from_user(data, data32, sizeof(*data32))) { - err = -EFAULT; - goto error; - } + data = memdup_user(data32, sizeof(*data32)); + if (IS_ERR(data)) + return PTR_ERR(data); + if (refine) err = snd_pcm_hw_refine(substream, data); else diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a151fb0..fc6f98e 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -327,21 +327,16 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params; int err; - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(params, _params, sizeof(*params))) { - err = -EFAULT; - goto out; - } + params = memdup_user(_params, sizeof(*params)); + if (IS_ERR(params)) + return PTR_ERR(params); + err = snd_pcm_hw_refine(substream, params); if (copy_to_user(_params, params, sizeof(*params))) { if (!err) err = -EFAULT; } -out: + kfree(params); return err; } @@ -465,21 +460,16 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params; int err; - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(params, _params, sizeof(*params))) { - err = -EFAULT; - goto out; - } + params = memdup_user(_params, sizeof(*params)); + if (IS_ERR(params)) + return PTR_ERR(params); + err = snd_pcm_hw_params(substream, params); if (copy_to_user(_params, params, sizeof(*params))) { if (!err) err = -EFAULT; } -out: + kfree(params); return err; } @@ -2593,13 +2583,11 @@ static int snd_pcm_playback_ioctl1(struct file *file, return -EFAULT; if (copy_from_user(&xfern, _xfern, sizeof(xfern))) return -EFAULT; - bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL); - if (bufs == NULL) - return -ENOMEM; - if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) { - kfree(bufs); - return -EFAULT; - } + + bufs = memdup_user(xfern.bufs, + sizeof(void *) * runtime->channels); + if (IS_ERR(bufs)) + return PTR_ERR(bufs); result = snd_pcm_lib_writev(substream, bufs, xfern.frames); kfree(bufs); __put_user(result, &_xfern->result); @@ -2675,13 +2663,11 @@ static int snd_pcm_capture_ioctl1(struct file *file, return -EFAULT; if (copy_from_user(&xfern, _xfern, sizeof(xfern))) return -EFAULT; - bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL); - if (bufs == NULL) - return -ENOMEM; - if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) { - kfree(bufs); - return -EFAULT; - } + + bufs = memdup_user(xfern.bufs, + sizeof(void *) * runtime->channels); + if (IS_ERR(bufs)) + return PTR_ERR(bufs); result = snd_pcm_lib_readv(substream, bufs, xfern.frames); kfree(bufs); __put_user(result, &_xfern->result); @@ -3312,18 +3298,12 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, int err; params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) { - err = -ENOMEM; - goto out; - } - oparams = kmalloc(sizeof(*oparams), GFP_KERNEL); - if (!oparams) { - err = -ENOMEM; - goto out; - } + if (!params) + return -ENOMEM; - if (copy_from_user(oparams, _oparams, sizeof(*oparams))) { - err = -EFAULT; + oparams = memdup_user(_oparams, sizeof(*oparams)); + if (IS_ERR(oparams)) { + err = PTR_ERR(oparams); goto out; } snd_pcm_hw_convert_from_old_params(params, oparams); @@ -3333,9 +3313,10 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, if (!err) err = -EFAULT; } + + kfree(oparams); out: kfree(params); - kfree(oparams); return err; } @@ -3347,17 +3328,12 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, int err; params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) { - err = -ENOMEM; - goto out; - } - oparams = kmalloc(sizeof(*oparams), GFP_KERNEL); - if (!oparams) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(oparams, _oparams, sizeof(*oparams))) { - err = -EFAULT; + if (!params) + return -ENOMEM; + + oparams = memdup_user(_oparams, sizeof(*oparams)); + if (IS_ERR(oparams)) { + err = PTR_ERR(oparams); goto out; } snd_pcm_hw_convert_from_old_params(params, oparams); @@ -3367,9 +3343,10 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, if (!err) err = -EFAULT; } + + kfree(oparams); out: kfree(params); - kfree(oparams); return err; } #endif /* CONFIG_SND_SUPPORT_OLD_API */ diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c index 38693f4..c956fe4 100644 --- a/sound/core/seq/seq_compat.c +++ b/sound/core/seq/seq_compat.c @@ -48,12 +48,11 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned struct snd_seq_port_info *data; mm_segment_t fs; - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (! data) - return -ENOMEM; + data = memdup_user(data32, sizeof(*data32)); + if (IS_ERR(data)) + return PTR_ERR(data); - if (copy_from_user(data, data32, sizeof(*data32)) || - get_user(data->flags, &data32->flags) || + if (get_user(data->flags, &data32->flags) || get_user(data->time_queue, &data32->time_queue)) goto error; data->kernel = NULL; diff --git a/sound/core/timer.c b/sound/core/timer.c index 3f0050d..8f8b17a 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1395,13 +1395,10 @@ static int snd_timer_user_ginfo(struct file *file, struct list_head *p; int err = 0; - ginfo = kmalloc(sizeof(*ginfo), GFP_KERNEL); - if (! ginfo) - return -ENOMEM; - if (copy_from_user(ginfo, _ginfo, sizeof(*ginfo))) { - kfree(ginfo); - return -EFAULT; - } + ginfo = memdup_user(_ginfo, sizeof(*ginfo)); + if (IS_ERR(ginfo)) + return PTR_ERR(ginfo); + tid = ginfo->tid; memset(ginfo, 0, sizeof(*ginfo)); ginfo->tid = tid; -- cgit v1.1 From 68425adcc419bfe90776f59e66b8c4cdb6e1b1f3 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 10 Apr 2009 09:43:36 +0800 Subject: ALSA: sound/isa: use memdup_user() Remove open-coded memdup_user(). Signed-off-by: Li Zefan Signed-off-by: Takashi Iwai --- sound/isa/sb/sb16_csp.c | 19 ++++++++++--------- sound/isa/wavefront/wavefront_fx.c | 14 +++++--------- sound/isa/wavefront/wavefront_synth.c | 11 +++++------ 3 files changed, 20 insertions(+), 24 deletions(-) (limited to 'sound') diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 49037d0..bdc8dde 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -684,15 +684,16 @@ static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags) { - int err = -ENOMEM; - unsigned char *kbuf = kmalloc(size, GFP_KERNEL); - if (kbuf) { - if (copy_from_user(kbuf, buf, size)) - err = -EFAULT; - else - err = snd_sb_csp_load(p, kbuf, size, load_flags); - kfree(kbuf); - } + int err; + unsigned char *kbuf; + + kbuf = memdup_user(buf, size); + if (IS_ERR(kbuf)) + return PTR_ERR(kbuf); + + err = snd_sb_csp_load(p, kbuf, size, load_flags); + + kfree(kbuf); return err; } diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index dfc449a..5e6870b 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c @@ -210,15 +210,11 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file, "> 512 bytes to FX\n"); return -EIO; } - page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL); - if (!page_data) - return -ENOMEM; - if (copy_from_user (page_data, - (unsigned char __user *) r.data[3], - r.data[2] * sizeof(short))) { - kfree(page_data); - return -EFAULT; - } + page_data = memdup_user((unsigned char __user *) + r.data[3], + r.data[2] * sizeof(short)); + if (IS_ERR(page_data)) + return PTR_ERR(page_data); pd = page_data; } diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index beb312c..5d4ff48 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -1664,12 +1664,11 @@ snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file, break; case WFCTL_WFCMD: - wc = kmalloc(sizeof(*wc), GFP_KERNEL); - if (! wc) - return -ENOMEM; - if (copy_from_user (wc, argp, sizeof (*wc))) - err = -EFAULT; - else if (wavefront_synth_control (acard, wc) < 0) + wc = memdup_user(argp, sizeof(*wc)); + if (IS_ERR(wc)) + return PTR_ERR(wc); + + if (wavefront_synth_control (acard, wc) < 0) err = -EIO; else if (copy_to_user (argp, wc, sizeof (*wc))) err = -EFAULT; -- cgit v1.1 From 85385c1551d509e9e377b7be07ea0e755fb2c3ce Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 10 Apr 2009 09:43:59 +0800 Subject: ALSA: sound/usb: use memdup_user() Remove open-coded memdup_user(). Signed-off-by: Li Zefan Signed-off-by: Takashi Iwai --- sound/usb/usx2y/us122l.c | 10 +++------- sound/usb/usx2y/usX2Yhwdep.c | 13 ++++++------- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 98276aa..012ff1f 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -349,14 +349,10 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, if (cmd != SNDRV_USB_STREAM_IOCTL_SET_PARAMS) return -ENOTTY; - cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); - if (!cfg) - return -ENOMEM; + cfg = memdup_user((void *)arg, sizeof(*cfg)); + if (IS_ERR(cfg)) + return PTR_ERR(cfg); - if (copy_from_user(cfg, (void *)arg, sizeof(*cfg))) { - err = -EFAULT; - goto free; - } if (cfg->version != USB_STREAM_INTERFACE_VERSION) { err = -ENXIO; goto free; diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 4af8740..f3d8f71 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -203,13 +203,12 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, if (access_ok(VERIFY_READ, dsp->image, dsp->length)) { struct usb_device* dev = priv->chip.dev; - char *buf = kmalloc(dsp->length, GFP_KERNEL); - if (!buf) - return -ENOMEM; - if (copy_from_user(buf, dsp->image, dsp->length)) { - kfree(buf); - return -EFAULT; - } + char *buf; + + buf = memdup_user(dsp->image, dsp->length); + if (IS_ERR(buf)) + return PTR_ERR(buf); + err = usb_set_interface(dev, 0, 1); if (err) snd_printk(KERN_ERR "usb_set_interface error \n"); -- cgit v1.1 From 336500f0305dc1552e8d01a60b409a7db781ca28 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 10 Apr 2009 09:44:31 +0800 Subject: ALSA: sound/pci: use memdup_user() Remove open-coded memdup_user(). Signed-off-by: Li Zefan Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/emufx.c | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) (limited to 'sound') diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 191e1cd..4b302d8 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -2493,24 +2493,17 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un case SNDRV_EMU10K1_IOCTL_CODE_POKE: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - icode = kmalloc(sizeof(*icode), GFP_KERNEL); - if (icode == NULL) - return -ENOMEM; - if (copy_from_user(icode, argp, sizeof(*icode))) { - kfree(icode); - return -EFAULT; - } + + icode = memdup_user(argp, sizeof(*icode)); + if (IS_ERR(icode)) + return PTR_ERR(icode); res = snd_emu10k1_icode_poke(emu, icode); kfree(icode); return res; case SNDRV_EMU10K1_IOCTL_CODE_PEEK: - icode = kmalloc(sizeof(*icode), GFP_KERNEL); - if (icode == NULL) - return -ENOMEM; - if (copy_from_user(icode, argp, sizeof(*icode))) { - kfree(icode); - return -EFAULT; - } + icode = memdup_user(argp, sizeof(*icode)); + if (IS_ERR(icode)) + return PTR_ERR(icode); res = snd_emu10k1_icode_peek(emu, icode); if (res == 0 && copy_to_user(argp, icode, sizeof(*icode))) { kfree(icode); @@ -2519,24 +2512,16 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un kfree(icode); return res; case SNDRV_EMU10K1_IOCTL_PCM_POKE: - ipcm = kmalloc(sizeof(*ipcm), GFP_KERNEL); - if (ipcm == NULL) - return -ENOMEM; - if (copy_from_user(ipcm, argp, sizeof(*ipcm))) { - kfree(ipcm); - return -EFAULT; - } + ipcm = memdup_user(argp, sizeof(*ipcm)); + if (IS_ERR(ipcm)) + return PTR_ERR(ipcm); res = snd_emu10k1_ipcm_poke(emu, ipcm); kfree(ipcm); return res; case SNDRV_EMU10K1_IOCTL_PCM_PEEK: - ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL); - if (ipcm == NULL) - return -ENOMEM; - if (copy_from_user(ipcm, argp, sizeof(*ipcm))) { - kfree(ipcm); - return -EFAULT; - } + ipcm = memdup_user(argp, sizeof(*ipcm)); + if (IS_ERR(ipcm)) + return PTR_ERR(ipcm); res = snd_emu10k1_ipcm_peek(emu, ipcm); if (res == 0 && copy_to_user(argp, ipcm, sizeof(*ipcm))) { kfree(ipcm); -- cgit v1.1 From e431cf45687d1ccb7c7d818defc2af34bd783db2 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Sat, 28 Mar 2009 21:19:49 +0100 Subject: ALSA: snd-usb-caiaq: clean up header includes Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/caiaq-audio.c | 8 +------- sound/usb/caiaq/caiaq-control.c | 6 +----- sound/usb/caiaq/caiaq-device.c | 13 +++---------- sound/usb/caiaq/caiaq-input.c | 6 ------ sound/usb/caiaq/caiaq-midi.c | 9 +-------- 5 files changed, 6 insertions(+), 36 deletions(-) (limited to 'sound') diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c index 08d51e0..cf37331 100644 --- a/sound/usb/caiaq/caiaq-audio.c +++ b/sound/usb/caiaq/caiaq-audio.c @@ -16,17 +16,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include -#include -#include -#include #include -#include #include -#include #include -#include -#include #include "caiaq-device.h" #include "caiaq-audio.h" diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c index e92c2bb..bb21fcf 100644 --- a/sound/usb/caiaq/caiaq-control.c +++ b/sound/usb/caiaq/caiaq-control.c @@ -18,14 +18,10 @@ */ #include -#include #include +#include #include -#include #include -#include -#include -#include #include "caiaq-device.h" #include "caiaq-control.h" diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index cf573a9..89f8b68 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c @@ -19,27 +19,20 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include #include #include +#include +#include #include -#include -#include -#include #include +#include #include -#include -#include #include "caiaq-device.h" #include "caiaq-audio.h" #include "caiaq-midi.h" #include "caiaq-control.h" - -#ifdef CONFIG_SND_USB_CAIAQ_INPUT #include "caiaq-input.h" -#endif MODULE_AUTHOR("Daniel Mack "); MODULE_DESCRIPTION("caiaq USB audio, version 1.3.13"); diff --git a/sound/usb/caiaq/caiaq-input.c b/sound/usb/caiaq/caiaq-input.c index f743847..4451775 100644 --- a/sound/usb/caiaq/caiaq-input.c +++ b/sound/usb/caiaq/caiaq-input.c @@ -17,14 +17,8 @@ */ #include -#include -#include -#include #include #include -#include -#include -#include #include #include "caiaq-device.h" #include "caiaq-input.h" diff --git a/sound/usb/caiaq/caiaq-midi.c b/sound/usb/caiaq/caiaq-midi.c index f19fd36..79424c1 100644 --- a/sound/usb/caiaq/caiaq-midi.c +++ b/sound/usb/caiaq/caiaq-midi.c @@ -16,21 +16,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include -#include -#include #include -#include -#include -#include #include +#include #include #include "caiaq-device.h" #include "caiaq-midi.h" - static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream) { return 0; -- cgit v1.1 From 936e7d03394bc6238091db10d060326622c87ed7 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 1 Apr 2009 19:05:39 +0200 Subject: ALSA: snd-usb-caiaq: rename files to remove redundant information in file pathes Cleanup only, no functional change. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/Makefile | 4 +- sound/usb/caiaq/audio.c | 700 ++++++++++++++++++++++++++++++++++++++++ sound/usb/caiaq/audio.h | 7 + sound/usb/caiaq/caiaq-audio.c | 700 ---------------------------------------- sound/usb/caiaq/caiaq-audio.h | 7 - sound/usb/caiaq/caiaq-control.c | 332 ------------------- sound/usb/caiaq/caiaq-control.h | 6 - sound/usb/caiaq/caiaq-device.c | 521 ------------------------------ sound/usb/caiaq/caiaq-device.h | 131 -------- sound/usb/caiaq/caiaq-input.c | 357 -------------------- sound/usb/caiaq/caiaq-input.h | 8 - sound/usb/caiaq/caiaq-midi.c | 173 ---------- sound/usb/caiaq/caiaq-midi.h | 8 - sound/usb/caiaq/control.c | 332 +++++++++++++++++++ sound/usb/caiaq/control.h | 6 + sound/usb/caiaq/device.c | 521 ++++++++++++++++++++++++++++++ sound/usb/caiaq/device.h | 131 ++++++++ sound/usb/caiaq/input.c | 358 ++++++++++++++++++++ sound/usb/caiaq/input.h | 8 + sound/usb/caiaq/midi.c | 173 ++++++++++ sound/usb/caiaq/midi.h | 8 + 21 files changed, 2246 insertions(+), 2245 deletions(-) create mode 100644 sound/usb/caiaq/audio.c create mode 100644 sound/usb/caiaq/audio.h delete mode 100644 sound/usb/caiaq/caiaq-audio.c delete mode 100644 sound/usb/caiaq/caiaq-audio.h delete mode 100644 sound/usb/caiaq/caiaq-control.c delete mode 100644 sound/usb/caiaq/caiaq-control.h delete mode 100644 sound/usb/caiaq/caiaq-device.c delete mode 100644 sound/usb/caiaq/caiaq-device.h delete mode 100644 sound/usb/caiaq/caiaq-input.c delete mode 100644 sound/usb/caiaq/caiaq-input.h delete mode 100644 sound/usb/caiaq/caiaq-midi.c delete mode 100644 sound/usb/caiaq/caiaq-midi.h create mode 100644 sound/usb/caiaq/control.c create mode 100644 sound/usb/caiaq/control.h create mode 100644 sound/usb/caiaq/device.c create mode 100644 sound/usb/caiaq/device.h create mode 100644 sound/usb/caiaq/input.c create mode 100644 sound/usb/caiaq/input.h create mode 100644 sound/usb/caiaq/midi.c create mode 100644 sound/usb/caiaq/midi.h (limited to 'sound') diff --git a/sound/usb/caiaq/Makefile b/sound/usb/caiaq/Makefile index 23dadd5..3889996 100644 --- a/sound/usb/caiaq/Makefile +++ b/sound/usb/caiaq/Makefile @@ -1,4 +1,4 @@ -snd-usb-caiaq-y := caiaq-device.o caiaq-audio.o caiaq-midi.o caiaq-control.o -snd-usb-caiaq-$(CONFIG_SND_USB_CAIAQ_INPUT) += caiaq-input.o +snd-usb-caiaq-y := device.o audio.o midi.o control.o +snd-usb-caiaq-$(CONFIG_SND_USB_CAIAQ_INPUT) += input.o obj-$(CONFIG_SND_USB_CAIAQ) += snd-usb-caiaq.o diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c new file mode 100644 index 0000000..3f45c0f --- /dev/null +++ b/sound/usb/caiaq/audio.c @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include + +#include "device.h" +#include "audio.h" + +#define N_URBS 32 +#define CLOCK_DRIFT_TOLERANCE 5 +#define FRAMES_PER_URB 8 +#define BYTES_PER_FRAME 512 +#define CHANNELS_PER_STREAM 2 +#define BYTES_PER_SAMPLE 3 +#define BYTES_PER_SAMPLE_USB 4 +#define MAX_BUFFER_SIZE (128*1024) +#define MAX_ENDPOINT_SIZE 512 + +#define ENDPOINT_CAPTURE 2 +#define ENDPOINT_PLAYBACK 6 + +#define MAKE_CHECKBYTE(dev,stream,i) \ + (stream << 1) | (~(i / (dev->n_streams * BYTES_PER_SAMPLE_USB)) & 1) + +static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER), + .formats = SNDRV_PCM_FMTBIT_S24_3BE, + .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000), + .rate_min = 44100, + .rate_max = 0, /* will overwrite later */ + .channels_min = CHANNELS_PER_STREAM, + .channels_max = CHANNELS_PER_STREAM, + .buffer_bytes_max = MAX_BUFFER_SIZE, + .period_bytes_min = 128, + .period_bytes_max = MAX_BUFFER_SIZE, + .periods_min = 1, + .periods_max = 1024, +}; + +static void +activate_substream(struct snd_usb_caiaqdev *dev, + struct snd_pcm_substream *sub) +{ + if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) + dev->sub_playback[sub->number] = sub; + else + dev->sub_capture[sub->number] = sub; +} + +static void +deactivate_substream(struct snd_usb_caiaqdev *dev, + struct snd_pcm_substream *sub) +{ + unsigned long flags; + spin_lock_irqsave(&dev->spinlock, flags); + + if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) + dev->sub_playback[sub->number] = NULL; + else + dev->sub_capture[sub->number] = NULL; + + spin_unlock_irqrestore(&dev->spinlock, flags); +} + +static int +all_substreams_zero(struct snd_pcm_substream **subs) +{ + int i; + for (i = 0; i < MAX_STREAMS; i++) + if (subs[i] != NULL) + return 0; + return 1; +} + +static int stream_start(struct snd_usb_caiaqdev *dev) +{ + int i, ret; + + debug("%s(%p)\n", __func__, dev); + + if (dev->streaming) + return -EINVAL; + + memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); + memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); + dev->input_panic = 0; + dev->output_panic = 0; + dev->first_packet = 1; + dev->streaming = 1; + dev->warned = 0; + + for (i = 0; i < N_URBS; i++) { + ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC); + if (ret) { + log("unable to trigger read #%d! (ret %d)\n", i, ret); + dev->streaming = 0; + return -EPIPE; + } + } + + return 0; +} + +static void stream_stop(struct snd_usb_caiaqdev *dev) +{ + int i; + + debug("%s(%p)\n", __func__, dev); + if (!dev->streaming) + return; + + dev->streaming = 0; + + for (i = 0; i < N_URBS; i++) { + usb_kill_urb(dev->data_urbs_in[i]); + usb_kill_urb(dev->data_urbs_out[i]); + } +} + +static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) +{ + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); + debug("%s(%p)\n", __func__, substream); + substream->runtime->hw = dev->pcm_info; + snd_pcm_limit_hw_rates(substream->runtime); + return 0; +} + +static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream) +{ + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); + + debug("%s(%p)\n", __func__, substream); + if (all_substreams_zero(dev->sub_playback) && + all_substreams_zero(dev->sub_capture)) { + /* when the last client has stopped streaming, + * all sample rates are allowed again */ + stream_stop(dev); + dev->pcm_info.rates = dev->samplerates; + } + + return 0; +} + +static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub, + struct snd_pcm_hw_params *hw_params) +{ + debug("%s(%p)\n", __func__, sub); + return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params)); +} + +static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) +{ + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); + debug("%s(%p)\n", __func__, sub); + deactivate_substream(dev, sub); + return snd_pcm_lib_free_pages(sub); +} + +/* this should probably go upstream */ +#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 +#error "Change this table" +#endif + +static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, + 48000, 64000, 88200, 96000, 176400, 192000 }; + +static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) +{ + int bytes_per_sample, bpp, ret, i; + int index = substream->number; + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + + debug("%s(%p)\n", __func__, substream); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1; + else + dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE; + + if (dev->streaming) + return 0; + + /* the first client that opens a stream defines the sample rate + * setting for all subsequent calls, until the last client closed. */ + for (i=0; i < ARRAY_SIZE(rates); i++) + if (runtime->rate == rates[i]) + dev->pcm_info.rates = 1 << i; + + snd_pcm_limit_hw_rates(runtime); + + bytes_per_sample = BYTES_PER_SAMPLE; + if (dev->spec.data_alignment == 2) + bytes_per_sample++; + + bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE) + * bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams; + + if (bpp > MAX_ENDPOINT_SIZE) + bpp = MAX_ENDPOINT_SIZE; + + ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate, + runtime->sample_bits, bpp); + if (ret) + return ret; + + ret = stream_start(dev); + if (ret) + return ret; + + dev->output_running = 0; + wait_event_timeout(dev->prepare_wait_queue, dev->output_running, HZ); + if (!dev->output_running) { + stream_stop(dev); + return -EPIPE; + } + + return 0; +} + +static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd) +{ + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + activate_substream(dev, sub); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + deactivate_substream(dev, sub); + break; + default: + return -EINVAL; + } + + return 0; +} + +static snd_pcm_uframes_t +snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) +{ + int index = sub->number; + struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); + + if (dev->input_panic || dev->output_panic) + return SNDRV_PCM_POS_XRUN; + + if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) + return bytes_to_frames(sub->runtime, + dev->audio_out_buf_pos[index]); + else + return bytes_to_frames(sub->runtime, + dev->audio_in_buf_pos[index]); +} + +/* operators for both playback and capture */ +static struct snd_pcm_ops snd_usb_caiaq_ops = { + .open = snd_usb_caiaq_substream_open, + .close = snd_usb_caiaq_substream_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = snd_usb_caiaq_pcm_hw_params, + .hw_free = snd_usb_caiaq_pcm_hw_free, + .prepare = snd_usb_caiaq_pcm_prepare, + .trigger = snd_usb_caiaq_pcm_trigger, + .pointer = snd_usb_caiaq_pcm_pointer +}; + +static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev, + struct snd_pcm_substream **subs) +{ + int stream, pb, *cnt; + struct snd_pcm_substream *sub; + + for (stream = 0; stream < dev->n_streams; stream++) { + sub = subs[stream]; + if (!sub) + continue; + + pb = frames_to_bytes(sub->runtime, + sub->runtime->period_size); + cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + &dev->period_out_count[stream] : + &dev->period_in_count[stream]; + + if (*cnt >= pb) { + snd_pcm_period_elapsed(sub); + *cnt %= pb; + } + } +} + +static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev, + const struct urb *urb, + const struct usb_iso_packet_descriptor *iso) +{ + unsigned char *usb_buf = urb->transfer_buffer + iso->offset; + struct snd_pcm_substream *sub; + int stream, i; + + if (all_substreams_zero(dev->sub_capture)) + return; + + for (i = 0; i < iso->actual_length;) { + for (stream = 0; stream < dev->n_streams; stream++, i++) { + sub = dev->sub_capture[stream]; + if (sub) { + struct snd_pcm_runtime *rt = sub->runtime; + char *audio_buf = rt->dma_area; + int sz = frames_to_bytes(rt, rt->buffer_size); + audio_buf[dev->audio_in_buf_pos[stream]++] + = usb_buf[i]; + dev->period_in_count[stream]++; + if (dev->audio_in_buf_pos[stream] == sz) + dev->audio_in_buf_pos[stream] = 0; + } + } + } +} + +static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev, + const struct urb *urb, + const struct usb_iso_packet_descriptor *iso) +{ + unsigned char *usb_buf = urb->transfer_buffer + iso->offset; + unsigned char check_byte; + struct snd_pcm_substream *sub; + int stream, i; + + for (i = 0; i < iso->actual_length;) { + if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) { + for (stream = 0; + stream < dev->n_streams; + stream++, i++) { + if (dev->first_packet) + continue; + + check_byte = MAKE_CHECKBYTE(dev, stream, i); + + if ((usb_buf[i] & 0x3f) != check_byte) + dev->input_panic = 1; + + if (usb_buf[i] & 0x80) + dev->output_panic = 1; + } + } + dev->first_packet = 0; + + for (stream = 0; stream < dev->n_streams; stream++, i++) { + sub = dev->sub_capture[stream]; + if (dev->input_panic) + usb_buf[i] = 0; + + if (sub) { + struct snd_pcm_runtime *rt = sub->runtime; + char *audio_buf = rt->dma_area; + int sz = frames_to_bytes(rt, rt->buffer_size); + audio_buf[dev->audio_in_buf_pos[stream]++] = + usb_buf[i]; + dev->period_in_count[stream]++; + if (dev->audio_in_buf_pos[stream] == sz) + dev->audio_in_buf_pos[stream] = 0; + } + } + } +} + +static void read_in_urb(struct snd_usb_caiaqdev *dev, + const struct urb *urb, + const struct usb_iso_packet_descriptor *iso) +{ + if (!dev->streaming) + return; + + if (iso->actual_length < dev->bpp) + return; + + switch (dev->spec.data_alignment) { + case 0: + read_in_urb_mode0(dev, urb, iso); + break; + case 2: + read_in_urb_mode2(dev, urb, iso); + break; + } + + if ((dev->input_panic || dev->output_panic) && !dev->warned) { + debug("streaming error detected %s %s\n", + dev->input_panic ? "(input)" : "", + dev->output_panic ? "(output)" : ""); + dev->warned = 1; + } +} + +static void fill_out_urb(struct snd_usb_caiaqdev *dev, + struct urb *urb, + const struct usb_iso_packet_descriptor *iso) +{ + unsigned char *usb_buf = urb->transfer_buffer + iso->offset; + struct snd_pcm_substream *sub; + int stream, i; + + for (i = 0; i < iso->length;) { + for (stream = 0; stream < dev->n_streams; stream++, i++) { + sub = dev->sub_playback[stream]; + if (sub) { + struct snd_pcm_runtime *rt = sub->runtime; + char *audio_buf = rt->dma_area; + int sz = frames_to_bytes(rt, rt->buffer_size); + usb_buf[i] = + audio_buf[dev->audio_out_buf_pos[stream]]; + dev->period_out_count[stream]++; + dev->audio_out_buf_pos[stream]++; + if (dev->audio_out_buf_pos[stream] == sz) + dev->audio_out_buf_pos[stream] = 0; + } else + usb_buf[i] = 0; + } + + /* fill in the check bytes */ + if (dev->spec.data_alignment == 2 && + i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == + (dev->n_streams * CHANNELS_PER_STREAM)) + for (stream = 0; stream < dev->n_streams; stream++, i++) + usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i); + } +} + +static void read_completed(struct urb *urb) +{ + struct snd_usb_caiaq_cb_info *info = urb->context; + struct snd_usb_caiaqdev *dev; + struct urb *out; + int frame, len, send_it = 0, outframe = 0; + + if (urb->status || !info) + return; + + dev = info->dev; + + if (!dev->streaming) + return; + + out = dev->data_urbs_out[info->index]; + + /* read the recently received packet and send back one which has + * the same layout */ + for (frame = 0; frame < FRAMES_PER_URB; frame++) { + if (urb->iso_frame_desc[frame].status) + continue; + + len = urb->iso_frame_desc[outframe].actual_length; + out->iso_frame_desc[outframe].length = len; + out->iso_frame_desc[outframe].actual_length = 0; + out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame; + + if (len > 0) { + spin_lock(&dev->spinlock); + fill_out_urb(dev, out, &out->iso_frame_desc[outframe]); + read_in_urb(dev, urb, &urb->iso_frame_desc[frame]); + spin_unlock(&dev->spinlock); + check_for_elapsed_periods(dev, dev->sub_playback); + check_for_elapsed_periods(dev, dev->sub_capture); + send_it = 1; + } + + outframe++; + } + + if (send_it) { + out->number_of_packets = FRAMES_PER_URB; + out->transfer_flags = URB_ISO_ASAP; + usb_submit_urb(out, GFP_ATOMIC); + } + + /* re-submit inbound urb */ + for (frame = 0; frame < FRAMES_PER_URB; frame++) { + urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; + urb->iso_frame_desc[frame].length = BYTES_PER_FRAME; + urb->iso_frame_desc[frame].actual_length = 0; + } + + urb->number_of_packets = FRAMES_PER_URB; + urb->transfer_flags = URB_ISO_ASAP; + usb_submit_urb(urb, GFP_ATOMIC); +} + +static void write_completed(struct urb *urb) +{ + struct snd_usb_caiaq_cb_info *info = urb->context; + struct snd_usb_caiaqdev *dev = info->dev; + + if (!dev->output_running) { + dev->output_running = 1; + wake_up(&dev->prepare_wait_queue); + } +} + +static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret) +{ + int i, frame; + struct urb **urbs; + struct usb_device *usb_dev = dev->chip.dev; + unsigned int pipe; + + pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ? + usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) : + usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE); + + urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL); + if (!urbs) { + log("unable to kmalloc() urbs, OOM!?\n"); + *ret = -ENOMEM; + return NULL; + } + + for (i = 0; i < N_URBS; i++) { + urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL); + if (!urbs[i]) { + log("unable to usb_alloc_urb(), OOM!?\n"); + *ret = -ENOMEM; + return urbs; + } + + urbs[i]->transfer_buffer = + kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL); + if (!urbs[i]->transfer_buffer) { + log("unable to kmalloc() transfer buffer, OOM!?\n"); + *ret = -ENOMEM; + return urbs; + } + + for (frame = 0; frame < FRAMES_PER_URB; frame++) { + struct usb_iso_packet_descriptor *iso = + &urbs[i]->iso_frame_desc[frame]; + + iso->offset = BYTES_PER_FRAME * frame; + iso->length = BYTES_PER_FRAME; + } + + urbs[i]->dev = usb_dev; + urbs[i]->pipe = pipe; + urbs[i]->transfer_buffer_length = FRAMES_PER_URB + * BYTES_PER_FRAME; + urbs[i]->context = &dev->data_cb_info[i]; + urbs[i]->interval = 1; + urbs[i]->transfer_flags = URB_ISO_ASAP; + urbs[i]->number_of_packets = FRAMES_PER_URB; + urbs[i]->complete = (dir == SNDRV_PCM_STREAM_CAPTURE) ? + read_completed : write_completed; + } + + *ret = 0; + return urbs; +} + +static void free_urbs(struct urb **urbs) +{ + int i; + + if (!urbs) + return; + + for (i = 0; i < N_URBS; i++) { + if (!urbs[i]) + continue; + + usb_kill_urb(urbs[i]); + kfree(urbs[i]->transfer_buffer); + usb_free_urb(urbs[i]); + } + + kfree(urbs); +} + +int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) +{ + int i, ret; + + dev->n_audio_in = max(dev->spec.num_analog_audio_in, + dev->spec.num_digital_audio_in) / + CHANNELS_PER_STREAM; + dev->n_audio_out = max(dev->spec.num_analog_audio_out, + dev->spec.num_digital_audio_out) / + CHANNELS_PER_STREAM; + dev->n_streams = max(dev->n_audio_in, dev->n_audio_out); + + debug("dev->n_audio_in = %d\n", dev->n_audio_in); + debug("dev->n_audio_out = %d\n", dev->n_audio_out); + debug("dev->n_streams = %d\n", dev->n_streams); + + if (dev->n_streams > MAX_STREAMS) { + log("unable to initialize device, too many streams.\n"); + return -EINVAL; + } + + ret = snd_pcm_new(dev->chip.card, dev->product_name, 0, + dev->n_audio_out, dev->n_audio_in, &dev->pcm); + + if (ret < 0) { + log("snd_pcm_new() returned %d\n", ret); + return ret; + } + + dev->pcm->private_data = dev; + strcpy(dev->pcm->name, dev->product_name); + + memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); + memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); + + memcpy(&dev->pcm_info, &snd_usb_caiaq_pcm_hardware, + sizeof(snd_usb_caiaq_pcm_hardware)); + + /* setup samplerates */ + dev->samplerates = dev->pcm_info.rates; + switch (dev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): + dev->samplerates |= SNDRV_PCM_RATE_192000; + /* fall thru */ + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): + dev->samplerates |= SNDRV_PCM_RATE_88200; + break; + } + + snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_usb_caiaq_ops); + snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_usb_caiaq_ops); + + snd_pcm_lib_preallocate_pages_for_all(dev->pcm, + SNDRV_DMA_TYPE_CONTINUOUS, + snd_dma_continuous_data(GFP_KERNEL), + MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); + + dev->data_cb_info = + kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, + GFP_KERNEL); + + if (!dev->data_cb_info) + return -ENOMEM; + + for (i = 0; i < N_URBS; i++) { + dev->data_cb_info[i].dev = dev; + dev->data_cb_info[i].index = i; + } + + dev->data_urbs_in = alloc_urbs(dev, SNDRV_PCM_STREAM_CAPTURE, &ret); + if (ret < 0) { + kfree(dev->data_cb_info); + free_urbs(dev->data_urbs_in); + return ret; + } + + dev->data_urbs_out = alloc_urbs(dev, SNDRV_PCM_STREAM_PLAYBACK, &ret); + if (ret < 0) { + kfree(dev->data_cb_info); + free_urbs(dev->data_urbs_in); + free_urbs(dev->data_urbs_out); + return ret; + } + + return 0; +} + +void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev) +{ + debug("%s(%p)\n", __func__, dev); + stream_stop(dev); + free_urbs(dev->data_urbs_in); + free_urbs(dev->data_urbs_out); + kfree(dev->data_cb_info); +} + diff --git a/sound/usb/caiaq/audio.h b/sound/usb/caiaq/audio.h new file mode 100644 index 0000000..8ab1f8d --- /dev/null +++ b/sound/usb/caiaq/audio.h @@ -0,0 +1,7 @@ +#ifndef CAIAQ_AUDIO_H +#define CAIAQ_AUDIO_H + +int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev); +void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev); + +#endif /* CAIAQ_AUDIO_H */ diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c deleted file mode 100644 index cf37331..0000000 --- a/sound/usb/caiaq/caiaq-audio.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright (c) 2006-2008 Daniel Mack, Karsten Wiese - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include - -#include "caiaq-device.h" -#include "caiaq-audio.h" - -#define N_URBS 32 -#define CLOCK_DRIFT_TOLERANCE 5 -#define FRAMES_PER_URB 8 -#define BYTES_PER_FRAME 512 -#define CHANNELS_PER_STREAM 2 -#define BYTES_PER_SAMPLE 3 -#define BYTES_PER_SAMPLE_USB 4 -#define MAX_BUFFER_SIZE (128*1024) -#define MAX_ENDPOINT_SIZE 512 - -#define ENDPOINT_CAPTURE 2 -#define ENDPOINT_PLAYBACK 6 - -#define MAKE_CHECKBYTE(dev,stream,i) \ - (stream << 1) | (~(i / (dev->n_streams * BYTES_PER_SAMPLE_USB)) & 1) - -static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER), - .formats = SNDRV_PCM_FMTBIT_S24_3BE, - .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_96000), - .rate_min = 44100, - .rate_max = 0, /* will overwrite later */ - .channels_min = CHANNELS_PER_STREAM, - .channels_max = CHANNELS_PER_STREAM, - .buffer_bytes_max = MAX_BUFFER_SIZE, - .period_bytes_min = 128, - .period_bytes_max = MAX_BUFFER_SIZE, - .periods_min = 1, - .periods_max = 1024, -}; - -static void -activate_substream(struct snd_usb_caiaqdev *dev, - struct snd_pcm_substream *sub) -{ - if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) - dev->sub_playback[sub->number] = sub; - else - dev->sub_capture[sub->number] = sub; -} - -static void -deactivate_substream(struct snd_usb_caiaqdev *dev, - struct snd_pcm_substream *sub) -{ - unsigned long flags; - spin_lock_irqsave(&dev->spinlock, flags); - - if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) - dev->sub_playback[sub->number] = NULL; - else - dev->sub_capture[sub->number] = NULL; - - spin_unlock_irqrestore(&dev->spinlock, flags); -} - -static int -all_substreams_zero(struct snd_pcm_substream **subs) -{ - int i; - for (i = 0; i < MAX_STREAMS; i++) - if (subs[i] != NULL) - return 0; - return 1; -} - -static int stream_start(struct snd_usb_caiaqdev *dev) -{ - int i, ret; - - debug("%s(%p)\n", __func__, dev); - - if (dev->streaming) - return -EINVAL; - - memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); - memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); - dev->input_panic = 0; - dev->output_panic = 0; - dev->first_packet = 1; - dev->streaming = 1; - dev->warned = 0; - - for (i = 0; i < N_URBS; i++) { - ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC); - if (ret) { - log("unable to trigger read #%d! (ret %d)\n", i, ret); - dev->streaming = 0; - return -EPIPE; - } - } - - return 0; -} - -static void stream_stop(struct snd_usb_caiaqdev *dev) -{ - int i; - - debug("%s(%p)\n", __func__, dev); - if (!dev->streaming) - return; - - dev->streaming = 0; - - for (i = 0; i < N_URBS; i++) { - usb_kill_urb(dev->data_urbs_in[i]); - usb_kill_urb(dev->data_urbs_out[i]); - } -} - -static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream) -{ - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); - debug("%s(%p)\n", __func__, substream); - substream->runtime->hw = dev->pcm_info; - snd_pcm_limit_hw_rates(substream->runtime); - return 0; -} - -static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream) -{ - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); - - debug("%s(%p)\n", __func__, substream); - if (all_substreams_zero(dev->sub_playback) && - all_substreams_zero(dev->sub_capture)) { - /* when the last client has stopped streaming, - * all sample rates are allowed again */ - stream_stop(dev); - dev->pcm_info.rates = dev->samplerates; - } - - return 0; -} - -static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub, - struct snd_pcm_hw_params *hw_params) -{ - debug("%s(%p)\n", __func__, sub); - return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params)); -} - -static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub) -{ - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); - debug("%s(%p)\n", __func__, sub); - deactivate_substream(dev, sub); - return snd_pcm_lib_free_pages(sub); -} - -/* this should probably go upstream */ -#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 -#error "Change this table" -#endif - -static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, - 48000, 64000, 88200, 96000, 176400, 192000 }; - -static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) -{ - int bytes_per_sample, bpp, ret, i; - int index = substream->number; - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - debug("%s(%p)\n", __func__, substream); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1; - else - dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE; - - if (dev->streaming) - return 0; - - /* the first client that opens a stream defines the sample rate - * setting for all subsequent calls, until the last client closed. */ - for (i=0; i < ARRAY_SIZE(rates); i++) - if (runtime->rate == rates[i]) - dev->pcm_info.rates = 1 << i; - - snd_pcm_limit_hw_rates(runtime); - - bytes_per_sample = BYTES_PER_SAMPLE; - if (dev->spec.data_alignment == 2) - bytes_per_sample++; - - bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE) - * bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams; - - if (bpp > MAX_ENDPOINT_SIZE) - bpp = MAX_ENDPOINT_SIZE; - - ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate, - runtime->sample_bits, bpp); - if (ret) - return ret; - - ret = stream_start(dev); - if (ret) - return ret; - - dev->output_running = 0; - wait_event_timeout(dev->prepare_wait_queue, dev->output_running, HZ); - if (!dev->output_running) { - stream_stop(dev); - return -EPIPE; - } - - return 0; -} - -static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd) -{ - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - activate_substream(dev, sub); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - deactivate_substream(dev, sub); - break; - default: - return -EINVAL; - } - - return 0; -} - -static snd_pcm_uframes_t -snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub) -{ - int index = sub->number; - struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); - - if (dev->input_panic || dev->output_panic) - return SNDRV_PCM_POS_XRUN; - - if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) - return bytes_to_frames(sub->runtime, - dev->audio_out_buf_pos[index]); - else - return bytes_to_frames(sub->runtime, - dev->audio_in_buf_pos[index]); -} - -/* operators for both playback and capture */ -static struct snd_pcm_ops snd_usb_caiaq_ops = { - .open = snd_usb_caiaq_substream_open, - .close = snd_usb_caiaq_substream_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_usb_caiaq_pcm_hw_params, - .hw_free = snd_usb_caiaq_pcm_hw_free, - .prepare = snd_usb_caiaq_pcm_prepare, - .trigger = snd_usb_caiaq_pcm_trigger, - .pointer = snd_usb_caiaq_pcm_pointer -}; - -static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev, - struct snd_pcm_substream **subs) -{ - int stream, pb, *cnt; - struct snd_pcm_substream *sub; - - for (stream = 0; stream < dev->n_streams; stream++) { - sub = subs[stream]; - if (!sub) - continue; - - pb = frames_to_bytes(sub->runtime, - sub->runtime->period_size); - cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - &dev->period_out_count[stream] : - &dev->period_in_count[stream]; - - if (*cnt >= pb) { - snd_pcm_period_elapsed(sub); - *cnt %= pb; - } - } -} - -static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev, - const struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - unsigned char *usb_buf = urb->transfer_buffer + iso->offset; - struct snd_pcm_substream *sub; - int stream, i; - - if (all_substreams_zero(dev->sub_capture)) - return; - - for (i = 0; i < iso->actual_length;) { - for (stream = 0; stream < dev->n_streams; stream++, i++) { - sub = dev->sub_capture[stream]; - if (sub) { - struct snd_pcm_runtime *rt = sub->runtime; - char *audio_buf = rt->dma_area; - int sz = frames_to_bytes(rt, rt->buffer_size); - audio_buf[dev->audio_in_buf_pos[stream]++] - = usb_buf[i]; - dev->period_in_count[stream]++; - if (dev->audio_in_buf_pos[stream] == sz) - dev->audio_in_buf_pos[stream] = 0; - } - } - } -} - -static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev, - const struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - unsigned char *usb_buf = urb->transfer_buffer + iso->offset; - unsigned char check_byte; - struct snd_pcm_substream *sub; - int stream, i; - - for (i = 0; i < iso->actual_length;) { - if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) { - for (stream = 0; - stream < dev->n_streams; - stream++, i++) { - if (dev->first_packet) - continue; - - check_byte = MAKE_CHECKBYTE(dev, stream, i); - - if ((usb_buf[i] & 0x3f) != check_byte) - dev->input_panic = 1; - - if (usb_buf[i] & 0x80) - dev->output_panic = 1; - } - } - dev->first_packet = 0; - - for (stream = 0; stream < dev->n_streams; stream++, i++) { - sub = dev->sub_capture[stream]; - if (dev->input_panic) - usb_buf[i] = 0; - - if (sub) { - struct snd_pcm_runtime *rt = sub->runtime; - char *audio_buf = rt->dma_area; - int sz = frames_to_bytes(rt, rt->buffer_size); - audio_buf[dev->audio_in_buf_pos[stream]++] = - usb_buf[i]; - dev->period_in_count[stream]++; - if (dev->audio_in_buf_pos[stream] == sz) - dev->audio_in_buf_pos[stream] = 0; - } - } - } -} - -static void read_in_urb(struct snd_usb_caiaqdev *dev, - const struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - if (!dev->streaming) - return; - - if (iso->actual_length < dev->bpp) - return; - - switch (dev->spec.data_alignment) { - case 0: - read_in_urb_mode0(dev, urb, iso); - break; - case 2: - read_in_urb_mode2(dev, urb, iso); - break; - } - - if ((dev->input_panic || dev->output_panic) && !dev->warned) { - debug("streaming error detected %s %s\n", - dev->input_panic ? "(input)" : "", - dev->output_panic ? "(output)" : ""); - dev->warned = 1; - } -} - -static void fill_out_urb(struct snd_usb_caiaqdev *dev, - struct urb *urb, - const struct usb_iso_packet_descriptor *iso) -{ - unsigned char *usb_buf = urb->transfer_buffer + iso->offset; - struct snd_pcm_substream *sub; - int stream, i; - - for (i = 0; i < iso->length;) { - for (stream = 0; stream < dev->n_streams; stream++, i++) { - sub = dev->sub_playback[stream]; - if (sub) { - struct snd_pcm_runtime *rt = sub->runtime; - char *audio_buf = rt->dma_area; - int sz = frames_to_bytes(rt, rt->buffer_size); - usb_buf[i] = - audio_buf[dev->audio_out_buf_pos[stream]]; - dev->period_out_count[stream]++; - dev->audio_out_buf_pos[stream]++; - if (dev->audio_out_buf_pos[stream] == sz) - dev->audio_out_buf_pos[stream] = 0; - } else - usb_buf[i] = 0; - } - - /* fill in the check bytes */ - if (dev->spec.data_alignment == 2 && - i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == - (dev->n_streams * CHANNELS_PER_STREAM)) - for (stream = 0; stream < dev->n_streams; stream++, i++) - usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i); - } -} - -static void read_completed(struct urb *urb) -{ - struct snd_usb_caiaq_cb_info *info = urb->context; - struct snd_usb_caiaqdev *dev; - struct urb *out; - int frame, len, send_it = 0, outframe = 0; - - if (urb->status || !info) - return; - - dev = info->dev; - - if (!dev->streaming) - return; - - out = dev->data_urbs_out[info->index]; - - /* read the recently received packet and send back one which has - * the same layout */ - for (frame = 0; frame < FRAMES_PER_URB; frame++) { - if (urb->iso_frame_desc[frame].status) - continue; - - len = urb->iso_frame_desc[outframe].actual_length; - out->iso_frame_desc[outframe].length = len; - out->iso_frame_desc[outframe].actual_length = 0; - out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame; - - if (len > 0) { - spin_lock(&dev->spinlock); - fill_out_urb(dev, out, &out->iso_frame_desc[outframe]); - read_in_urb(dev, urb, &urb->iso_frame_desc[frame]); - spin_unlock(&dev->spinlock); - check_for_elapsed_periods(dev, dev->sub_playback); - check_for_elapsed_periods(dev, dev->sub_capture); - send_it = 1; - } - - outframe++; - } - - if (send_it) { - out->number_of_packets = FRAMES_PER_URB; - out->transfer_flags = URB_ISO_ASAP; - usb_submit_urb(out, GFP_ATOMIC); - } - - /* re-submit inbound urb */ - for (frame = 0; frame < FRAMES_PER_URB; frame++) { - urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame; - urb->iso_frame_desc[frame].length = BYTES_PER_FRAME; - urb->iso_frame_desc[frame].actual_length = 0; - } - - urb->number_of_packets = FRAMES_PER_URB; - urb->transfer_flags = URB_ISO_ASAP; - usb_submit_urb(urb, GFP_ATOMIC); -} - -static void write_completed(struct urb *urb) -{ - struct snd_usb_caiaq_cb_info *info = urb->context; - struct snd_usb_caiaqdev *dev = info->dev; - - if (!dev->output_running) { - dev->output_running = 1; - wake_up(&dev->prepare_wait_queue); - } -} - -static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret) -{ - int i, frame; - struct urb **urbs; - struct usb_device *usb_dev = dev->chip.dev; - unsigned int pipe; - - pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ? - usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) : - usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE); - - urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL); - if (!urbs) { - log("unable to kmalloc() urbs, OOM!?\n"); - *ret = -ENOMEM; - return NULL; - } - - for (i = 0; i < N_URBS; i++) { - urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL); - if (!urbs[i]) { - log("unable to usb_alloc_urb(), OOM!?\n"); - *ret = -ENOMEM; - return urbs; - } - - urbs[i]->transfer_buffer = - kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL); - if (!urbs[i]->transfer_buffer) { - log("unable to kmalloc() transfer buffer, OOM!?\n"); - *ret = -ENOMEM; - return urbs; - } - - for (frame = 0; frame < FRAMES_PER_URB; frame++) { - struct usb_iso_packet_descriptor *iso = - &urbs[i]->iso_frame_desc[frame]; - - iso->offset = BYTES_PER_FRAME * frame; - iso->length = BYTES_PER_FRAME; - } - - urbs[i]->dev = usb_dev; - urbs[i]->pipe = pipe; - urbs[i]->transfer_buffer_length = FRAMES_PER_URB - * BYTES_PER_FRAME; - urbs[i]->context = &dev->data_cb_info[i]; - urbs[i]->interval = 1; - urbs[i]->transfer_flags = URB_ISO_ASAP; - urbs[i]->number_of_packets = FRAMES_PER_URB; - urbs[i]->complete = (dir == SNDRV_PCM_STREAM_CAPTURE) ? - read_completed : write_completed; - } - - *ret = 0; - return urbs; -} - -static void free_urbs(struct urb **urbs) -{ - int i; - - if (!urbs) - return; - - for (i = 0; i < N_URBS; i++) { - if (!urbs[i]) - continue; - - usb_kill_urb(urbs[i]); - kfree(urbs[i]->transfer_buffer); - usb_free_urb(urbs[i]); - } - - kfree(urbs); -} - -int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) -{ - int i, ret; - - dev->n_audio_in = max(dev->spec.num_analog_audio_in, - dev->spec.num_digital_audio_in) / - CHANNELS_PER_STREAM; - dev->n_audio_out = max(dev->spec.num_analog_audio_out, - dev->spec.num_digital_audio_out) / - CHANNELS_PER_STREAM; - dev->n_streams = max(dev->n_audio_in, dev->n_audio_out); - - debug("dev->n_audio_in = %d\n", dev->n_audio_in); - debug("dev->n_audio_out = %d\n", dev->n_audio_out); - debug("dev->n_streams = %d\n", dev->n_streams); - - if (dev->n_streams > MAX_STREAMS) { - log("unable to initialize device, too many streams.\n"); - return -EINVAL; - } - - ret = snd_pcm_new(dev->chip.card, dev->product_name, 0, - dev->n_audio_out, dev->n_audio_in, &dev->pcm); - - if (ret < 0) { - log("snd_pcm_new() returned %d\n", ret); - return ret; - } - - dev->pcm->private_data = dev; - strcpy(dev->pcm->name, dev->product_name); - - memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); - memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); - - memcpy(&dev->pcm_info, &snd_usb_caiaq_pcm_hardware, - sizeof(snd_usb_caiaq_pcm_hardware)); - - /* setup samplerates */ - dev->samplerates = dev->pcm_info.rates; - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): - dev->samplerates |= SNDRV_PCM_RATE_192000; - /* fall thru */ - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): - dev->samplerates |= SNDRV_PCM_RATE_88200; - break; - } - - snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_usb_caiaq_ops); - snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_usb_caiaq_ops); - - snd_pcm_lib_preallocate_pages_for_all(dev->pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); - - dev->data_cb_info = - kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, - GFP_KERNEL); - - if (!dev->data_cb_info) - return -ENOMEM; - - for (i = 0; i < N_URBS; i++) { - dev->data_cb_info[i].dev = dev; - dev->data_cb_info[i].index = i; - } - - dev->data_urbs_in = alloc_urbs(dev, SNDRV_PCM_STREAM_CAPTURE, &ret); - if (ret < 0) { - kfree(dev->data_cb_info); - free_urbs(dev->data_urbs_in); - return ret; - } - - dev->data_urbs_out = alloc_urbs(dev, SNDRV_PCM_STREAM_PLAYBACK, &ret); - if (ret < 0) { - kfree(dev->data_cb_info); - free_urbs(dev->data_urbs_in); - free_urbs(dev->data_urbs_out); - return ret; - } - - return 0; -} - -void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev) -{ - debug("%s(%p)\n", __func__, dev); - stream_stop(dev); - free_urbs(dev->data_urbs_in); - free_urbs(dev->data_urbs_out); - kfree(dev->data_cb_info); -} - diff --git a/sound/usb/caiaq/caiaq-audio.h b/sound/usb/caiaq/caiaq-audio.h deleted file mode 100644 index 8ab1f8d..0000000 --- a/sound/usb/caiaq/caiaq-audio.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef CAIAQ_AUDIO_H -#define CAIAQ_AUDIO_H - -int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev); -void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev); - -#endif /* CAIAQ_AUDIO_H */ diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c deleted file mode 100644 index bb21fcf..0000000 --- a/sound/usb/caiaq/caiaq-control.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2007 Daniel Mack - * friendly supported by NI. - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -#include "caiaq-device.h" -#include "caiaq-control.h" - -#define CNT_INTVAL 0x10000 - -static int control_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); - struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); - int pos = kcontrol->private_value; - int is_intval = pos & CNT_INTVAL; - unsigned int id = dev->chip.usb_id; - - uinfo->count = 1; - pos &= ~CNT_INTVAL; - - if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ) - && (pos == 0)) { - /* current input mode of A8DJ */ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 2; - return 0; - } - - if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ) - && (pos == 0)) { - /* current input mode of A4DJ */ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; - } - - if (is_intval) { - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 64; - } else { - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - } - - return 0; -} - -static int control_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); - struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); - int pos = kcontrol->private_value; - - if (dev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) { - /* A4DJ has only one control */ - /* do not expose hardware input mode 0 */ - ucontrol->value.integer.value[0] = dev->control_state[0] - 1; - return 0; - } - - if (pos & CNT_INTVAL) - ucontrol->value.integer.value[0] - = dev->control_state[pos & ~CNT_INTVAL]; - else - ucontrol->value.integer.value[0] - = !!(dev->control_state[pos / 8] & (1 << pos % 8)); - - return 0; -} - -static int control_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); - struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); - int pos = kcontrol->private_value; - - if (dev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) { - /* A4DJ has only one control */ - /* do not expose hardware input mode 0 */ - dev->control_state[0] = ucontrol->value.integer.value[0] + 1; - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, - dev->control_state, sizeof(dev->control_state)); - return 1; - } - - if (pos & CNT_INTVAL) { - dev->control_state[pos & ~CNT_INTVAL] - = ucontrol->value.integer.value[0]; - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, - dev->control_state, sizeof(dev->control_state)); - } else { - if (ucontrol->value.integer.value[0]) - dev->control_state[pos / 8] |= 1 << (pos % 8); - else - dev->control_state[pos / 8] &= ~(1 << (pos % 8)); - - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, - dev->control_state, sizeof(dev->control_state)); - } - - return 1; -} - -static struct snd_kcontrol_new kcontrol_template __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .index = 0, - .info = control_info, - .get = control_get, - .put = control_put, - /* name and private_value filled later */ -}; - -struct caiaq_controller { - char *name; - int index; -}; - -static struct caiaq_controller ak1_controller[] = { - { "LED left", 2 }, - { "LED middle", 1 }, - { "LED right", 0 }, - { "LED ring", 3 } -}; - -static struct caiaq_controller rk2_controller[] = { - { "LED 1", 5 }, - { "LED 2", 4 }, - { "LED 3", 3 }, - { "LED 4", 2 }, - { "LED 5", 1 }, - { "LED 6", 0 }, - { "LED pedal", 6 }, - { "LED 7seg_1b", 8 }, - { "LED 7seg_1c", 9 }, - { "LED 7seg_2a", 10 }, - { "LED 7seg_2b", 11 }, - { "LED 7seg_2c", 12 }, - { "LED 7seg_2d", 13 }, - { "LED 7seg_2e", 14 }, - { "LED 7seg_2f", 15 }, - { "LED 7seg_2g", 16 }, - { "LED 7seg_3a", 17 }, - { "LED 7seg_3b", 18 }, - { "LED 7seg_3c", 19 }, - { "LED 7seg_3d", 20 }, - { "LED 7seg_3e", 21 }, - { "LED 7seg_3f", 22 }, - { "LED 7seg_3g", 23 } -}; - -static struct caiaq_controller rk3_controller[] = { - { "LED 7seg_1a", 0 + 0 }, - { "LED 7seg_1b", 0 + 1 }, - { "LED 7seg_1c", 0 + 2 }, - { "LED 7seg_1d", 0 + 3 }, - { "LED 7seg_1e", 0 + 4 }, - { "LED 7seg_1f", 0 + 5 }, - { "LED 7seg_1g", 0 + 6 }, - { "LED 7seg_1p", 0 + 7 }, - - { "LED 7seg_2a", 8 + 0 }, - { "LED 7seg_2b", 8 + 1 }, - { "LED 7seg_2c", 8 + 2 }, - { "LED 7seg_2d", 8 + 3 }, - { "LED 7seg_2e", 8 + 4 }, - { "LED 7seg_2f", 8 + 5 }, - { "LED 7seg_2g", 8 + 6 }, - { "LED 7seg_2p", 8 + 7 }, - - { "LED 7seg_3a", 16 + 0 }, - { "LED 7seg_3b", 16 + 1 }, - { "LED 7seg_3c", 16 + 2 }, - { "LED 7seg_3d", 16 + 3 }, - { "LED 7seg_3e", 16 + 4 }, - { "LED 7seg_3f", 16 + 5 }, - { "LED 7seg_3g", 16 + 6 }, - { "LED 7seg_3p", 16 + 7 }, - - { "LED 7seg_4a", 24 + 0 }, - { "LED 7seg_4b", 24 + 1 }, - { "LED 7seg_4c", 24 + 2 }, - { "LED 7seg_4d", 24 + 3 }, - { "LED 7seg_4e", 24 + 4 }, - { "LED 7seg_4f", 24 + 5 }, - { "LED 7seg_4g", 24 + 6 }, - { "LED 7seg_4p", 24 + 7 }, - - { "LED 1", 32 + 0 }, - { "LED 2", 32 + 1 }, - { "LED 3", 32 + 2 }, - { "LED 4", 32 + 3 }, - { "LED 5", 32 + 4 }, - { "LED 6", 32 + 5 }, - { "LED 7", 32 + 6 }, - { "LED 8", 32 + 7 }, - { "LED pedal", 32 + 8 } -}; - -static struct caiaq_controller kore_controller[] = { - { "LED F1", 8 | CNT_INTVAL }, - { "LED F2", 12 | CNT_INTVAL }, - { "LED F3", 0 | CNT_INTVAL }, - { "LED F4", 4 | CNT_INTVAL }, - { "LED F5", 11 | CNT_INTVAL }, - { "LED F6", 15 | CNT_INTVAL }, - { "LED F7", 3 | CNT_INTVAL }, - { "LED F8", 7 | CNT_INTVAL }, - { "LED touch1", 10 | CNT_INTVAL }, - { "LED touch2", 14 | CNT_INTVAL }, - { "LED touch3", 2 | CNT_INTVAL }, - { "LED touch4", 6 | CNT_INTVAL }, - { "LED touch5", 9 | CNT_INTVAL }, - { "LED touch6", 13 | CNT_INTVAL }, - { "LED touch7", 1 | CNT_INTVAL }, - { "LED touch8", 5 | CNT_INTVAL }, - { "LED left", 18 | CNT_INTVAL }, - { "LED right", 22 | CNT_INTVAL }, - { "LED up", 16 | CNT_INTVAL }, - { "LED down", 20 | CNT_INTVAL }, - { "LED stop", 23 | CNT_INTVAL }, - { "LED play", 21 | CNT_INTVAL }, - { "LED record", 19 | CNT_INTVAL }, - { "LED listen", 17 | CNT_INTVAL }, - { "LED lcd", 30 | CNT_INTVAL }, - { "LED menu", 28 | CNT_INTVAL }, - { "LED sound", 31 | CNT_INTVAL }, - { "LED esc", 29 | CNT_INTVAL }, - { "LED view", 27 | CNT_INTVAL }, - { "LED enter", 24 | CNT_INTVAL }, - { "LED control", 26 | CNT_INTVAL } -}; - -static struct caiaq_controller a8dj_controller[] = { - { "Current input mode", 0 | CNT_INTVAL }, - { "GND lift for TC Vinyl mode", 24 + 0 }, - { "GND lift for TC CD/Line mode", 24 + 1 }, - { "GND lift for phono mode", 24 + 2 }, - { "Software lock", 40 } -}; - -static struct caiaq_controller a4dj_controller[] = { - { "Current input mode", 0 | CNT_INTVAL } -}; - -static int __devinit add_controls(struct caiaq_controller *c, int num, - struct snd_usb_caiaqdev *dev) -{ - int i, ret; - struct snd_kcontrol *kc; - - for (i = 0; i < num; i++, c++) { - kcontrol_template.name = c->name; - kcontrol_template.private_value = c->index; - kc = snd_ctl_new1(&kcontrol_template, dev); - ret = snd_ctl_add(dev->chip.card, kc); - if (ret < 0) - return ret; - } - - return 0; -} - -int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev) -{ - int ret = 0; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - ret = add_controls(ak1_controller, - ARRAY_SIZE(ak1_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): - ret = add_controls(rk2_controller, - ARRAY_SIZE(rk2_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - ret = add_controls(rk3_controller, - ARRAY_SIZE(rk3_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - ret = add_controls(kore_controller, - ARRAY_SIZE(kore_controller), dev); - break; - - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): - ret = add_controls(a8dj_controller, - ARRAY_SIZE(a8dj_controller), dev); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): - ret = add_controls(a4dj_controller, - ARRAY_SIZE(a4dj_controller), dev); - break; - } - - return ret; -} - diff --git a/sound/usb/caiaq/caiaq-control.h b/sound/usb/caiaq/caiaq-control.h deleted file mode 100644 index 2e7ab1a..0000000 --- a/sound/usb/caiaq/caiaq-control.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef CAIAQ_CONTROL_H -#define CAIAQ_CONTROL_H - -int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev); - -#endif /* CAIAQ_CONTROL_H */ diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c deleted file mode 100644 index 89f8b68..0000000 --- a/sound/usb/caiaq/caiaq-device.c +++ /dev/null @@ -1,521 +0,0 @@ -/* - * caiaq.c: ALSA driver for caiaq/NativeInstruments devices - * - * Copyright (c) 2007 Daniel Mack - * Karsten Wiese - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "caiaq-device.h" -#include "caiaq-audio.h" -#include "caiaq-midi.h" -#include "caiaq-control.h" -#include "caiaq-input.h" - -MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("caiaq USB audio, version 1.3.13"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," - "{Native Instruments, RigKontrol3}," - "{Native Instruments, Kore Controller}," - "{Native Instruments, Kore Controller 2}," - "{Native Instruments, Audio Kontrol 1}," - "{Native Instruments, Audio 4 DJ}," - "{Native Instruments, Audio 8 DJ}," - "{Native Instruments, Session I/O}," - "{Native Instruments, GuitarRig mobile}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ -static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int snd_card_used[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the caiaq sound device"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the caiaq soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable the caiaq soundcard."); - -enum { - SAMPLERATE_44100 = 0, - SAMPLERATE_48000 = 1, - SAMPLERATE_96000 = 2, - SAMPLERATE_192000 = 3, - SAMPLERATE_88200 = 4, - SAMPLERATE_INVALID = 0xff -}; - -enum { - DEPTH_NONE = 0, - DEPTH_16 = 1, - DEPTH_24 = 2, - DEPTH_32 = 3 -}; - -static struct usb_device_id snd_usb_id_table[] = { - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_RIGKONTROL2 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_RIGKONTROL3 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_KORECONTROLLER - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_KORECONTROLLER2 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_AK1 - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_AUDIO8DJ - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_SESSIONIO - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_GUITARRIGMOBILE - }, - { - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = USB_VID_NATIVEINSTRUMENTS, - .idProduct = USB_PID_AUDIO4DJ - }, - { /* terminator */ } -}; - -static void usb_ep1_command_reply_dispatch (struct urb* urb) -{ - int ret; - struct snd_usb_caiaqdev *dev = urb->context; - unsigned char *buf = urb->transfer_buffer; - - if (urb->status || !dev) { - log("received EP1 urb->status = %i\n", urb->status); - return; - } - - switch(buf[0]) { - case EP1_CMD_GET_DEVICE_INFO: - memcpy(&dev->spec, buf+1, sizeof(struct caiaq_device_spec)); - dev->spec.fw_version = le16_to_cpu(dev->spec.fw_version); - debug("device spec (firmware %d): audio: %d in, %d out, " - "MIDI: %d in, %d out, data alignment %d\n", - dev->spec.fw_version, - dev->spec.num_analog_audio_in, - dev->spec.num_analog_audio_out, - dev->spec.num_midi_in, - dev->spec.num_midi_out, - dev->spec.data_alignment); - - dev->spec_received++; - wake_up(&dev->ep1_wait_queue); - break; - case EP1_CMD_AUDIO_PARAMS: - dev->audio_parm_answer = buf[1]; - wake_up(&dev->ep1_wait_queue); - break; - case EP1_CMD_MIDI_READ: - snd_usb_caiaq_midi_handle_input(dev, buf[1], buf + 3, buf[2]); - break; - case EP1_CMD_READ_IO: - if (dev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)) { - if (urb->actual_length > sizeof(dev->control_state)) - urb->actual_length = sizeof(dev->control_state); - memcpy(dev->control_state, buf + 1, urb->actual_length); - wake_up(&dev->ep1_wait_queue); - break; - } -#ifdef CONFIG_SND_USB_CAIAQ_INPUT - case EP1_CMD_READ_ERP: - case EP1_CMD_READ_ANALOG: - snd_usb_caiaq_input_dispatch(dev, buf, urb->actual_length); -#endif - break; - } - - dev->ep1_in_urb.actual_length = 0; - ret = usb_submit_urb(&dev->ep1_in_urb, GFP_ATOMIC); - if (ret < 0) - log("unable to submit urb. OOM!?\n"); -} - -int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *dev, - unsigned char command, - const unsigned char *buffer, - int len) -{ - int actual_len; - struct usb_device *usb_dev = dev->chip.dev; - - if (!usb_dev) - return -EIO; - - if (len > EP1_BUFSIZE - 1) - len = EP1_BUFSIZE - 1; - - if (buffer && len > 0) - memcpy(dev->ep1_out_buf+1, buffer, len); - - dev->ep1_out_buf[0] = command; - return usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, 1), - dev->ep1_out_buf, len+1, &actual_len, 200); -} - -int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, - int rate, int depth, int bpp) -{ - int ret; - char tmp[5]; - - switch (rate) { - case 44100: tmp[0] = SAMPLERATE_44100; break; - case 48000: tmp[0] = SAMPLERATE_48000; break; - case 88200: tmp[0] = SAMPLERATE_88200; break; - case 96000: tmp[0] = SAMPLERATE_96000; break; - case 192000: tmp[0] = SAMPLERATE_192000; break; - default: return -EINVAL; - } - - switch (depth) { - case 16: tmp[1] = DEPTH_16; break; - case 24: tmp[1] = DEPTH_24; break; - default: return -EINVAL; - } - - tmp[2] = bpp & 0xff; - tmp[3] = bpp >> 8; - tmp[4] = 1; /* packets per microframe */ - - debug("setting audio params: %d Hz, %d bits, %d bpp\n", - rate, depth, bpp); - - dev->audio_parm_answer = -1; - ret = snd_usb_caiaq_send_command(dev, EP1_CMD_AUDIO_PARAMS, - tmp, sizeof(tmp)); - - if (ret) - return ret; - - if (!wait_event_timeout(dev->ep1_wait_queue, - dev->audio_parm_answer >= 0, HZ)) - return -EPIPE; - - if (dev->audio_parm_answer != 1) - debug("unable to set the device's audio params\n"); - else - dev->bpp = bpp; - - return dev->audio_parm_answer == 1 ? 0 : -EINVAL; -} - -int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, - int digital, int analog, int erp) -{ - char tmp[3] = { digital, analog, erp }; - return snd_usb_caiaq_send_command(dev, EP1_CMD_AUTO_MSG, - tmp, sizeof(tmp)); -} - -static void __devinit setup_card(struct snd_usb_caiaqdev *dev) -{ - int ret; - char val[4]; - - /* device-specific startup specials */ - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): - /* RigKontrol2 - display centered dash ('-') */ - val[0] = 0x00; - val[1] = 0x00; - val[2] = 0x01; - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 3); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - /* RigKontrol2 - display two centered dashes ('--') */ - val[0] = 0x00; - val[1] = 0x40; - val[2] = 0x40; - val[3] = 0x00; - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 4); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - /* Audio Kontrol 1 - make USB-LED stop blinking */ - val[0] = 0x00; - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 1); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): - /* Audio 8 DJ - trigger read of current settings */ - dev->control_state[0] = 0xff; - snd_usb_caiaq_set_auto_msg(dev, 1, 0, 0); - snd_usb_caiaq_send_command(dev, EP1_CMD_READ_IO, NULL, 0); - - if (!wait_event_timeout(dev->ep1_wait_queue, - dev->control_state[0] != 0xff, HZ)) - return; - - /* fix up some defaults */ - if ((dev->control_state[1] != 2) || - (dev->control_state[2] != 3) || - (dev->control_state[4] != 2)) { - dev->control_state[1] = 2; - dev->control_state[2] = 3; - dev->control_state[4] = 2; - snd_usb_caiaq_send_command(dev, - EP1_CMD_WRITE_IO, dev->control_state, 6); - } - - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): - /* Audio 4 DJ - default input mode to phono */ - dev->control_state[0] = 2; - snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, - dev->control_state, 1); - break; - } - - if (dev->spec.num_analog_audio_out + - dev->spec.num_analog_audio_in + - dev->spec.num_digital_audio_out + - dev->spec.num_digital_audio_in > 0) { - ret = snd_usb_caiaq_audio_init(dev); - if (ret < 0) - log("Unable to set up audio system (ret=%d)\n", ret); - } - - if (dev->spec.num_midi_in + - dev->spec.num_midi_out > 0) { - ret = snd_usb_caiaq_midi_init(dev); - if (ret < 0) - log("Unable to set up MIDI system (ret=%d)\n", ret); - } - -#ifdef CONFIG_SND_USB_CAIAQ_INPUT - ret = snd_usb_caiaq_input_init(dev); - if (ret < 0) - log("Unable to set up input system (ret=%d)\n", ret); -#endif - - /* finally, register the card and all its sub-instances */ - ret = snd_card_register(dev->chip.card); - if (ret < 0) { - log("snd_card_register() returned %d\n", ret); - snd_card_free(dev->chip.card); - } - - ret = snd_usb_caiaq_control_init(dev); - if (ret < 0) - log("Unable to set up control system (ret=%d)\n", ret); -} - -static int create_card(struct usb_device* usb_dev, struct snd_card **cardp) -{ - int devnum; - int err; - struct snd_card *card; - struct snd_usb_caiaqdev *dev; - - for (devnum = 0; devnum < SNDRV_CARDS; devnum++) - if (enable[devnum] && !snd_card_used[devnum]) - break; - - if (devnum >= SNDRV_CARDS) - return -ENODEV; - - err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, - sizeof(struct snd_usb_caiaqdev), &card); - if (err < 0) - return err; - - dev = caiaqdev(card); - dev->chip.dev = usb_dev; - dev->chip.card = card; - dev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct)); - spin_lock_init(&dev->spinlock); - snd_card_set_dev(card, &usb_dev->dev); - - *cardp = card; - return 0; -} - -static int __devinit init_card(struct snd_usb_caiaqdev *dev) -{ - char *c; - struct usb_device *usb_dev = dev->chip.dev; - struct snd_card *card = dev->chip.card; - int err, len; - - if (usb_set_interface(usb_dev, 0, 1) != 0) { - log("can't set alt interface.\n"); - return -EIO; - } - - usb_init_urb(&dev->ep1_in_urb); - usb_init_urb(&dev->midi_out_urb); - - usb_fill_bulk_urb(&dev->ep1_in_urb, usb_dev, - usb_rcvbulkpipe(usb_dev, 0x1), - dev->ep1_in_buf, EP1_BUFSIZE, - usb_ep1_command_reply_dispatch, dev); - - usb_fill_bulk_urb(&dev->midi_out_urb, usb_dev, - usb_sndbulkpipe(usb_dev, 0x1), - dev->midi_out_buf, EP1_BUFSIZE, - snd_usb_caiaq_midi_output_done, dev); - - init_waitqueue_head(&dev->ep1_wait_queue); - init_waitqueue_head(&dev->prepare_wait_queue); - - if (usb_submit_urb(&dev->ep1_in_urb, GFP_KERNEL) != 0) - return -EIO; - - err = snd_usb_caiaq_send_command(dev, EP1_CMD_GET_DEVICE_INFO, NULL, 0); - if (err) - return err; - - if (!wait_event_timeout(dev->ep1_wait_queue, dev->spec_received, HZ)) - return -ENODEV; - - usb_string(usb_dev, usb_dev->descriptor.iManufacturer, - dev->vendor_name, CAIAQ_USB_STR_LEN); - - usb_string(usb_dev, usb_dev->descriptor.iProduct, - dev->product_name, CAIAQ_USB_STR_LEN); - - usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, - dev->serial, CAIAQ_USB_STR_LEN); - - /* terminate serial string at first white space occurence */ - c = strchr(dev->serial, ' '); - if (c) - *c = '\0'; - - strcpy(card->driver, MODNAME); - strcpy(card->shortname, dev->product_name); - - len = snprintf(card->longname, sizeof(card->longname), - "%s %s (serial %s, ", - dev->vendor_name, dev->product_name, dev->serial); - - if (len < sizeof(card->longname) - 2) - len += usb_make_path(usb_dev, card->longname + len, - sizeof(card->longname) - len); - - card->longname[len++] = ')'; - card->longname[len] = '\0'; - setup_card(dev); - return 0; -} - -static int __devinit snd_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int ret; - struct snd_card *card; - struct usb_device *device = interface_to_usbdev(intf); - - ret = create_card(device, &card); - - if (ret < 0) - return ret; - - usb_set_intfdata(intf, card); - ret = init_card(caiaqdev(card)); - if (ret < 0) { - log("unable to init card! (ret=%d)\n", ret); - snd_card_free(card); - return ret; - } - - return 0; -} - -static void snd_disconnect(struct usb_interface *intf) -{ - struct snd_usb_caiaqdev *dev; - struct snd_card *card = usb_get_intfdata(intf); - - debug("%s(%p)\n", __func__, intf); - - if (!card) - return; - - dev = caiaqdev(card); - snd_card_disconnect(card); - -#ifdef CONFIG_SND_USB_CAIAQ_INPUT - snd_usb_caiaq_input_free(dev); -#endif - snd_usb_caiaq_audio_free(dev); - - usb_kill_urb(&dev->ep1_in_urb); - usb_kill_urb(&dev->midi_out_urb); - - snd_card_free(card); - usb_reset_device(interface_to_usbdev(intf)); -} - - -MODULE_DEVICE_TABLE(usb, snd_usb_id_table); -static struct usb_driver snd_usb_driver = { - .name = MODNAME, - .probe = snd_probe, - .disconnect = snd_disconnect, - .id_table = snd_usb_id_table, -}; - -static int __init snd_module_init(void) -{ - return usb_register(&snd_usb_driver); -} - -static void __exit snd_module_exit(void) -{ - usb_deregister(&snd_usb_driver); -} - -module_init(snd_module_init) -module_exit(snd_module_exit) - diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h deleted file mode 100644 index 4cce1ad..0000000 --- a/sound/usb/caiaq/caiaq-device.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef CAIAQ_DEVICE_H -#define CAIAQ_DEVICE_H - -#include "../usbaudio.h" - -#define USB_VID_NATIVEINSTRUMENTS 0x17cc - -#define USB_PID_RIGKONTROL2 0x1969 -#define USB_PID_RIGKONTROL3 0x1940 -#define USB_PID_KORECONTROLLER 0x4711 -#define USB_PID_KORECONTROLLER2 0x4712 -#define USB_PID_AK1 0x0815 -#define USB_PID_AUDIO4DJ 0x0839 -#define USB_PID_AUDIO8DJ 0x1978 -#define USB_PID_SESSIONIO 0x1915 -#define USB_PID_GUITARRIGMOBILE 0x0d8d - -#define EP1_BUFSIZE 64 -#define CAIAQ_USB_STR_LEN 0xff -#define MAX_STREAMS 32 - -//#define SND_USB_CAIAQ_DEBUG - -#define MODNAME "snd-usb-caiaq" -#define log(x...) snd_printk(KERN_WARNING MODNAME" log: " x) - -#ifdef SND_USB_CAIAQ_DEBUG -#define debug(x...) snd_printk(KERN_WARNING MODNAME " debug: " x) -#else -#define debug(x...) do { } while(0) -#endif - -#define EP1_CMD_GET_DEVICE_INFO 0x1 -#define EP1_CMD_READ_ERP 0x2 -#define EP1_CMD_READ_ANALOG 0x3 -#define EP1_CMD_READ_IO 0x4 -#define EP1_CMD_WRITE_IO 0x5 -#define EP1_CMD_MIDI_READ 0x6 -#define EP1_CMD_MIDI_WRITE 0x7 -#define EP1_CMD_AUDIO_PARAMS 0x9 -#define EP1_CMD_AUTO_MSG 0xb -#define EP1_CMD_DIMM_LEDS 0xc - -struct caiaq_device_spec { - unsigned short fw_version; - unsigned char hw_subtype; - unsigned char num_erp; - unsigned char num_analog_in; - unsigned char num_digital_in; - unsigned char num_digital_out; - unsigned char num_analog_audio_out; - unsigned char num_analog_audio_in; - unsigned char num_digital_audio_out; - unsigned char num_digital_audio_in; - unsigned char num_midi_out; - unsigned char num_midi_in; - unsigned char data_alignment; -} __attribute__ ((packed)); - -struct snd_usb_caiaq_cb_info; - -struct snd_usb_caiaqdev { - struct snd_usb_audio chip; - - struct urb ep1_in_urb; - struct urb midi_out_urb; - struct urb **data_urbs_in; - struct urb **data_urbs_out; - struct snd_usb_caiaq_cb_info *data_cb_info; - - unsigned char ep1_in_buf[EP1_BUFSIZE]; - unsigned char ep1_out_buf[EP1_BUFSIZE]; - unsigned char midi_out_buf[EP1_BUFSIZE]; - - struct caiaq_device_spec spec; - spinlock_t spinlock; - wait_queue_head_t ep1_wait_queue; - wait_queue_head_t prepare_wait_queue; - int spec_received, audio_parm_answer; - int midi_out_active; - - char vendor_name[CAIAQ_USB_STR_LEN]; - char product_name[CAIAQ_USB_STR_LEN]; - char serial[CAIAQ_USB_STR_LEN]; - - int n_streams, n_audio_in, n_audio_out; - int streaming, first_packet, output_running; - int audio_in_buf_pos[MAX_STREAMS]; - int audio_out_buf_pos[MAX_STREAMS]; - int period_in_count[MAX_STREAMS]; - int period_out_count[MAX_STREAMS]; - int input_panic, output_panic, warned; - char *audio_in_buf, *audio_out_buf; - unsigned int samplerates, bpp; - - struct snd_pcm_substream *sub_playback[MAX_STREAMS]; - struct snd_pcm_substream *sub_capture[MAX_STREAMS]; - - /* Controls */ - unsigned char control_state[64]; - - /* Linux input */ -#ifdef CONFIG_SND_USB_CAIAQ_INPUT - struct input_dev *input_dev; - char phys[64]; /* physical device path */ - unsigned short keycode[64]; -#endif - - /* ALSA */ - struct snd_pcm *pcm; - struct snd_pcm_hardware pcm_info; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *midi_receive_substream; - struct snd_rawmidi_substream *midi_out_substream; -}; - -struct snd_usb_caiaq_cb_info { - struct snd_usb_caiaqdev *dev; - int index; -}; - -#define caiaqdev(c) ((struct snd_usb_caiaqdev*)(c)->private_data) - -int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, int rate, int depth, int bbp); -int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, int digital, int analog, int erp); -int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *dev, - unsigned char command, - const unsigned char *buffer, - int len); - -#endif /* CAIAQ_DEVICE_H */ diff --git a/sound/usb/caiaq/caiaq-input.c b/sound/usb/caiaq/caiaq-input.c deleted file mode 100644 index 4451775..0000000 --- a/sound/usb/caiaq/caiaq-input.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2006,2007 Daniel Mack, Tim Ruetz - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include "caiaq-device.h" -#include "caiaq-input.h" - -static unsigned short keycode_ak1[] = { KEY_C, KEY_B, KEY_A }; -static unsigned short keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4, - KEY_5, KEY_6, KEY_7 }; -static unsigned short keycode_rk3[] = { KEY_1, KEY_2, KEY_3, KEY_4, - KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 }; - -static unsigned short keycode_kore[] = { - KEY_FN_F1, /* "menu" */ - KEY_FN_F7, /* "lcd backlight */ - KEY_FN_F2, /* "control" */ - KEY_FN_F3, /* "enter" */ - KEY_FN_F4, /* "view" */ - KEY_FN_F5, /* "esc" */ - KEY_FN_F6, /* "sound" */ - KEY_FN_F8, /* array spacer, never triggered. */ - KEY_RIGHT, - KEY_DOWN, - KEY_UP, - KEY_LEFT, - KEY_SOUND, /* "listen" */ - KEY_RECORD, - KEY_PLAYPAUSE, - KEY_STOP, - BTN_4, /* 8 softkeys */ - BTN_3, - BTN_2, - BTN_1, - BTN_8, - BTN_7, - BTN_6, - BTN_5, - KEY_BRL_DOT4, /* touch sensitive knobs */ - KEY_BRL_DOT3, - KEY_BRL_DOT2, - KEY_BRL_DOT1, - KEY_BRL_DOT8, - KEY_BRL_DOT7, - KEY_BRL_DOT6, - KEY_BRL_DOT5 -}; - -#define DEG90 (range / 2) -#define DEG180 (range) -#define DEG270 (DEG90 + DEG180) -#define DEG360 (DEG180 * 2) -#define HIGH_PEAK (268) -#define LOW_PEAK (-7) - -/* some of these devices have endless rotation potentiometers - * built in which use two tapers, 90 degrees phase shifted. - * this algorithm decodes them to one single value, ranging - * from 0 to 999 */ -static unsigned int decode_erp(unsigned char a, unsigned char b) -{ - int weight_a, weight_b; - int pos_a, pos_b; - int ret; - int range = HIGH_PEAK - LOW_PEAK; - int mid_value = (HIGH_PEAK + LOW_PEAK) / 2; - - weight_b = abs(mid_value - a) - (range / 2 - 100) / 2; - - if (weight_b < 0) - weight_b = 0; - - if (weight_b > 100) - weight_b = 100; - - weight_a = 100 - weight_b; - - if (a < mid_value) { - /* 0..90 and 270..360 degrees */ - pos_b = b - LOW_PEAK + DEG270; - if (pos_b >= DEG360) - pos_b -= DEG360; - } else - /* 90..270 degrees */ - pos_b = HIGH_PEAK - b + DEG90; - - - if (b > mid_value) - /* 0..180 degrees */ - pos_a = a - LOW_PEAK; - else - /* 180..360 degrees */ - pos_a = HIGH_PEAK - a + DEG180; - - /* interpolate both slider values, depending on weight factors */ - /* 0..99 x DEG360 */ - ret = pos_a * weight_a + pos_b * weight_b; - - /* normalize to 0..999 */ - ret *= 10; - ret /= DEG360; - - if (ret < 0) - ret += 1000; - - if (ret >= 1000) - ret -= 1000; - - return ret; -} - -#undef DEG90 -#undef DEG180 -#undef DEG270 -#undef DEG360 -#undef HIGH_PEAK -#undef LOW_PEAK - - -static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev, - const unsigned char *buf, - unsigned int len) -{ - struct input_dev *input_dev = dev->input_dev; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): - input_report_abs(input_dev, ABS_X, (buf[4] << 8) | buf[5]); - input_report_abs(input_dev, ABS_Y, (buf[0] << 8) | buf[1]); - input_report_abs(input_dev, ABS_Z, (buf[2] << 8) | buf[3]); - input_sync(input_dev); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]); - input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]); - input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]); - input_sync(input_dev); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]); - input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]); - input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]); - input_sync(input_dev); - break; - } -} - -static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev, - const char *buf, unsigned int len) -{ - struct input_dev *input_dev = dev->input_dev; - int i; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - i = decode_erp(buf[0], buf[1]); - input_report_abs(input_dev, ABS_X, i); - input_sync(input_dev); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - i = decode_erp(buf[7], buf[5]); - input_report_abs(input_dev, ABS_HAT0X, i); - i = decode_erp(buf[12], buf[14]); - input_report_abs(input_dev, ABS_HAT0Y, i); - i = decode_erp(buf[15], buf[13]); - input_report_abs(input_dev, ABS_HAT1X, i); - i = decode_erp(buf[0], buf[2]); - input_report_abs(input_dev, ABS_HAT1Y, i); - i = decode_erp(buf[3], buf[1]); - input_report_abs(input_dev, ABS_HAT2X, i); - i = decode_erp(buf[8], buf[10]); - input_report_abs(input_dev, ABS_HAT2Y, i); - i = decode_erp(buf[11], buf[9]); - input_report_abs(input_dev, ABS_HAT3X, i); - i = decode_erp(buf[4], buf[6]); - input_report_abs(input_dev, ABS_HAT3Y, i); - input_sync(input_dev); - break; - } -} - -static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev, - char *buf, unsigned int len) -{ - struct input_dev *input_dev = dev->input_dev; - unsigned short *keycode = input_dev->keycode; - int i; - - if (!keycode) - return; - - if (input_dev->id.product == USB_PID_RIGKONTROL2) - for (i = 0; i < len; i++) - buf[i] = ~buf[i]; - - for (i = 0; i < input_dev->keycodemax && i < len * 8; i++) - input_report_key(input_dev, keycode[i], - buf[i / 8] & (1 << (i % 8))); - - if (dev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER) || - dev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2)) - input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]); - - input_sync(input_dev); -} - -void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, - char *buf, - unsigned int len) -{ - if (!dev->input_dev || len < 1) - return; - - switch (buf[0]) { - case EP1_CMD_READ_ANALOG: - snd_caiaq_input_read_analog(dev, buf + 1, len - 1); - break; - case EP1_CMD_READ_ERP: - snd_caiaq_input_read_erp(dev, buf + 1, len - 1); - break; - case EP1_CMD_READ_IO: - snd_caiaq_input_read_io(dev, buf + 1, len - 1); - break; - } -} - -int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev) -{ - struct usb_device *usb_dev = dev->chip.dev; - struct input_dev *input; - int i, ret; - - input = input_allocate_device(); - if (!input) - return -ENOMEM; - - usb_make_path(usb_dev, dev->phys, sizeof(dev->phys)); - strlcat(dev->phys, "/input0", sizeof(dev->phys)); - - input->name = dev->product_name; - input->phys = dev->phys; - usb_to_input_id(usb_dev, &input->id); - input->dev.parent = &usb_dev->dev; - - switch (dev->chip.usb_id) { - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | - BIT_MASK(ABS_Z); - BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk2)); - memcpy(dev->keycode, keycode_rk2, sizeof(keycode_rk2)); - input->keycodemax = ARRAY_SIZE(keycode_rk2); - input_set_abs_params(input, ABS_X, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10); - snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | - BIT_MASK(ABS_Z); - BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk3)); - memcpy(dev->keycode, keycode_rk3, sizeof(keycode_rk3)); - input->keycodemax = ARRAY_SIZE(keycode_rk3); - input_set_abs_params(input, ABS_X, 0, 1024, 0, 10); - input_set_abs_params(input, ABS_Y, 0, 1024, 0, 10); - input_set_abs_params(input, ABS_Z, 0, 1024, 0, 10); - snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_X); - BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_ak1)); - memcpy(dev->keycode, keycode_ak1, sizeof(keycode_ak1)); - input->keycodemax = ARRAY_SIZE(keycode_ak1); - input_set_abs_params(input, ABS_X, 0, 999, 0, 10); - snd_usb_caiaq_set_auto_msg(dev, 1, 0, 5); - break; - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): - case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): - input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) | - BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) | - BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) | - BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) | - BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | - BIT_MASK(ABS_Z); - input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); - BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_kore)); - memcpy(dev->keycode, keycode_kore, sizeof(keycode_kore)); - input->keycodemax = ARRAY_SIZE(keycode_kore); - input_set_abs_params(input, ABS_HAT0X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT0Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT1X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT1Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT2X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT2Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT3X, 0, 999, 0, 10); - input_set_abs_params(input, ABS_HAT3Y, 0, 999, 0, 10); - input_set_abs_params(input, ABS_X, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10); - input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1); - snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5); - break; - default: - /* no input methods supported on this device */ - input_free_device(input); - return 0; - } - - input->keycode = dev->keycode; - input->keycodesize = sizeof(unsigned short); - for (i = 0; i < input->keycodemax; i++) - __set_bit(dev->keycode[i], input->keybit); - - ret = input_register_device(input); - if (ret < 0) { - input_free_device(input); - return ret; - } - - dev->input_dev = input; - return 0; -} - -void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev) -{ - if (!dev || !dev->input_dev) - return; - - input_unregister_device(dev->input_dev); - dev->input_dev = NULL; -} - diff --git a/sound/usb/caiaq/caiaq-input.h b/sound/usb/caiaq/caiaq-input.h deleted file mode 100644 index ced5355..0000000 --- a/sound/usb/caiaq/caiaq-input.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CAIAQ_INPUT_H -#define CAIAQ_INPUT_H - -void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, char *buf, unsigned int len); -int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev); -void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev); - -#endif diff --git a/sound/usb/caiaq/caiaq-midi.c b/sound/usb/caiaq/caiaq-midi.c deleted file mode 100644 index 79424c1..0000000 --- a/sound/usb/caiaq/caiaq-midi.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2006,2007 Daniel Mack - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include - -#include "caiaq-device.h" -#include "caiaq-midi.h" - -static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; - - if (!dev) - return; - - dev->midi_receive_substream = up ? substream : NULL; -} - - -static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substream) -{ - return 0; -} - -static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; - if (dev->midi_out_active) { - usb_kill_urb(&dev->midi_out_urb); - dev->midi_out_active = 0; - } - return 0; -} - -static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, - struct snd_rawmidi_substream *substream) -{ - int len, ret; - - dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; - dev->midi_out_buf[1] = 0; /* port */ - len = snd_rawmidi_transmit(substream, dev->midi_out_buf + 3, - EP1_BUFSIZE - 3); - - if (len <= 0) - return; - - dev->midi_out_buf[2] = len; - dev->midi_out_urb.transfer_buffer_length = len+3; - - ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); - if (ret < 0) - log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed," - "ret=%d, len=%d\n", - substream, ret, len); - else - dev->midi_out_active = 1; -} - -static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; - - if (up) { - dev->midi_out_substream = substream; - if (!dev->midi_out_active) - snd_usb_caiaq_midi_send(dev, substream); - } else { - dev->midi_out_substream = NULL; - } -} - - -static struct snd_rawmidi_ops snd_usb_caiaq_midi_output = -{ - .open = snd_usb_caiaq_midi_output_open, - .close = snd_usb_caiaq_midi_output_close, - .trigger = snd_usb_caiaq_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_usb_caiaq_midi_input = -{ - .open = snd_usb_caiaq_midi_input_open, - .close = snd_usb_caiaq_midi_input_close, - .trigger = snd_usb_caiaq_midi_input_trigger, -}; - -void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, - int port, const char *buf, int len) -{ - if (!dev->midi_receive_substream) - return; - - snd_rawmidi_receive(dev->midi_receive_substream, buf, len); -} - -int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device) -{ - int ret; - struct snd_rawmidi *rmidi; - - ret = snd_rawmidi_new(device->chip.card, device->product_name, 0, - device->spec.num_midi_out, - device->spec.num_midi_in, - &rmidi); - - if (ret < 0) - return ret; - - strcpy(rmidi->name, device->product_name); - - rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = device; - - if (device->spec.num_midi_out > 0) { - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_usb_caiaq_midi_output); - } - - if (device->spec.num_midi_in > 0) { - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_usb_caiaq_midi_input); - } - - device->rmidi = rmidi; - - return 0; -} - -void snd_usb_caiaq_midi_output_done(struct urb* urb) -{ - struct snd_usb_caiaqdev *dev = urb->context; - - dev->midi_out_active = 0; - if (urb->status != 0) - return; - - if (!dev->midi_out_substream) - return; - - snd_usb_caiaq_midi_send(dev, dev->midi_out_substream); -} - diff --git a/sound/usb/caiaq/caiaq-midi.h b/sound/usb/caiaq/caiaq-midi.h deleted file mode 100644 index 9d16db0..0000000 --- a/sound/usb/caiaq/caiaq-midi.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CAIAQ_MIDI_H -#define CAIAQ_MIDI_H - -int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev); -void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len); -void snd_usb_caiaq_midi_output_done(struct urb* urb); - -#endif /* CAIAQ_MIDI_H */ diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c new file mode 100644 index 0000000..537102b --- /dev/null +++ b/sound/usb/caiaq/control.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2007 Daniel Mack + * friendly supported by NI. + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include "device.h" +#include "control.h" + +#define CNT_INTVAL 0x10000 + +static int control_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); + struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); + int pos = kcontrol->private_value; + int is_intval = pos & CNT_INTVAL; + unsigned int id = dev->chip.usb_id; + + uinfo->count = 1; + pos &= ~CNT_INTVAL; + + if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ) + && (pos == 0)) { + /* current input mode of A8DJ */ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 2; + return 0; + } + + if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ) + && (pos == 0)) { + /* current input mode of A4DJ */ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; + } + + if (is_intval) { + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 64; + } else { + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + } + + return 0; +} + +static int control_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); + struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); + int pos = kcontrol->private_value; + + if (dev->chip.usb_id == + USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) { + /* A4DJ has only one control */ + /* do not expose hardware input mode 0 */ + ucontrol->value.integer.value[0] = dev->control_state[0] - 1; + return 0; + } + + if (pos & CNT_INTVAL) + ucontrol->value.integer.value[0] + = dev->control_state[pos & ~CNT_INTVAL]; + else + ucontrol->value.integer.value[0] + = !!(dev->control_state[pos / 8] & (1 << pos % 8)); + + return 0; +} + +static int control_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); + struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); + int pos = kcontrol->private_value; + + if (dev->chip.usb_id == + USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) { + /* A4DJ has only one control */ + /* do not expose hardware input mode 0 */ + dev->control_state[0] = ucontrol->value.integer.value[0] + 1; + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, + dev->control_state, sizeof(dev->control_state)); + return 1; + } + + if (pos & CNT_INTVAL) { + dev->control_state[pos & ~CNT_INTVAL] + = ucontrol->value.integer.value[0]; + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, + dev->control_state, sizeof(dev->control_state)); + } else { + if (ucontrol->value.integer.value[0]) + dev->control_state[pos / 8] |= 1 << (pos % 8); + else + dev->control_state[pos / 8] &= ~(1 << (pos % 8)); + + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, + dev->control_state, sizeof(dev->control_state)); + } + + return 1; +} + +static struct snd_kcontrol_new kcontrol_template __devinitdata = { + .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .index = 0, + .info = control_info, + .get = control_get, + .put = control_put, + /* name and private_value filled later */ +}; + +struct caiaq_controller { + char *name; + int index; +}; + +static struct caiaq_controller ak1_controller[] = { + { "LED left", 2 }, + { "LED middle", 1 }, + { "LED right", 0 }, + { "LED ring", 3 } +}; + +static struct caiaq_controller rk2_controller[] = { + { "LED 1", 5 }, + { "LED 2", 4 }, + { "LED 3", 3 }, + { "LED 4", 2 }, + { "LED 5", 1 }, + { "LED 6", 0 }, + { "LED pedal", 6 }, + { "LED 7seg_1b", 8 }, + { "LED 7seg_1c", 9 }, + { "LED 7seg_2a", 10 }, + { "LED 7seg_2b", 11 }, + { "LED 7seg_2c", 12 }, + { "LED 7seg_2d", 13 }, + { "LED 7seg_2e", 14 }, + { "LED 7seg_2f", 15 }, + { "LED 7seg_2g", 16 }, + { "LED 7seg_3a", 17 }, + { "LED 7seg_3b", 18 }, + { "LED 7seg_3c", 19 }, + { "LED 7seg_3d", 20 }, + { "LED 7seg_3e", 21 }, + { "LED 7seg_3f", 22 }, + { "LED 7seg_3g", 23 } +}; + +static struct caiaq_controller rk3_controller[] = { + { "LED 7seg_1a", 0 + 0 }, + { "LED 7seg_1b", 0 + 1 }, + { "LED 7seg_1c", 0 + 2 }, + { "LED 7seg_1d", 0 + 3 }, + { "LED 7seg_1e", 0 + 4 }, + { "LED 7seg_1f", 0 + 5 }, + { "LED 7seg_1g", 0 + 6 }, + { "LED 7seg_1p", 0 + 7 }, + + { "LED 7seg_2a", 8 + 0 }, + { "LED 7seg_2b", 8 + 1 }, + { "LED 7seg_2c", 8 + 2 }, + { "LED 7seg_2d", 8 + 3 }, + { "LED 7seg_2e", 8 + 4 }, + { "LED 7seg_2f", 8 + 5 }, + { "LED 7seg_2g", 8 + 6 }, + { "LED 7seg_2p", 8 + 7 }, + + { "LED 7seg_3a", 16 + 0 }, + { "LED 7seg_3b", 16 + 1 }, + { "LED 7seg_3c", 16 + 2 }, + { "LED 7seg_3d", 16 + 3 }, + { "LED 7seg_3e", 16 + 4 }, + { "LED 7seg_3f", 16 + 5 }, + { "LED 7seg_3g", 16 + 6 }, + { "LED 7seg_3p", 16 + 7 }, + + { "LED 7seg_4a", 24 + 0 }, + { "LED 7seg_4b", 24 + 1 }, + { "LED 7seg_4c", 24 + 2 }, + { "LED 7seg_4d", 24 + 3 }, + { "LED 7seg_4e", 24 + 4 }, + { "LED 7seg_4f", 24 + 5 }, + { "LED 7seg_4g", 24 + 6 }, + { "LED 7seg_4p", 24 + 7 }, + + { "LED 1", 32 + 0 }, + { "LED 2", 32 + 1 }, + { "LED 3", 32 + 2 }, + { "LED 4", 32 + 3 }, + { "LED 5", 32 + 4 }, + { "LED 6", 32 + 5 }, + { "LED 7", 32 + 6 }, + { "LED 8", 32 + 7 }, + { "LED pedal", 32 + 8 } +}; + +static struct caiaq_controller kore_controller[] = { + { "LED F1", 8 | CNT_INTVAL }, + { "LED F2", 12 | CNT_INTVAL }, + { "LED F3", 0 | CNT_INTVAL }, + { "LED F4", 4 | CNT_INTVAL }, + { "LED F5", 11 | CNT_INTVAL }, + { "LED F6", 15 | CNT_INTVAL }, + { "LED F7", 3 | CNT_INTVAL }, + { "LED F8", 7 | CNT_INTVAL }, + { "LED touch1", 10 | CNT_INTVAL }, + { "LED touch2", 14 | CNT_INTVAL }, + { "LED touch3", 2 | CNT_INTVAL }, + { "LED touch4", 6 | CNT_INTVAL }, + { "LED touch5", 9 | CNT_INTVAL }, + { "LED touch6", 13 | CNT_INTVAL }, + { "LED touch7", 1 | CNT_INTVAL }, + { "LED touch8", 5 | CNT_INTVAL }, + { "LED left", 18 | CNT_INTVAL }, + { "LED right", 22 | CNT_INTVAL }, + { "LED up", 16 | CNT_INTVAL }, + { "LED down", 20 | CNT_INTVAL }, + { "LED stop", 23 | CNT_INTVAL }, + { "LED play", 21 | CNT_INTVAL }, + { "LED record", 19 | CNT_INTVAL }, + { "LED listen", 17 | CNT_INTVAL }, + { "LED lcd", 30 | CNT_INTVAL }, + { "LED menu", 28 | CNT_INTVAL }, + { "LED sound", 31 | CNT_INTVAL }, + { "LED esc", 29 | CNT_INTVAL }, + { "LED view", 27 | CNT_INTVAL }, + { "LED enter", 24 | CNT_INTVAL }, + { "LED control", 26 | CNT_INTVAL } +}; + +static struct caiaq_controller a8dj_controller[] = { + { "Current input mode", 0 | CNT_INTVAL }, + { "GND lift for TC Vinyl mode", 24 + 0 }, + { "GND lift for TC CD/Line mode", 24 + 1 }, + { "GND lift for phono mode", 24 + 2 }, + { "Software lock", 40 } +}; + +static struct caiaq_controller a4dj_controller[] = { + { "Current input mode", 0 | CNT_INTVAL } +}; + +static int __devinit add_controls(struct caiaq_controller *c, int num, + struct snd_usb_caiaqdev *dev) +{ + int i, ret; + struct snd_kcontrol *kc; + + for (i = 0; i < num; i++, c++) { + kcontrol_template.name = c->name; + kcontrol_template.private_value = c->index; + kc = snd_ctl_new1(&kcontrol_template, dev); + ret = snd_ctl_add(dev->chip.card, kc); + if (ret < 0) + return ret; + } + + return 0; +} + +int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev) +{ + int ret = 0; + + switch (dev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): + ret = add_controls(ak1_controller, + ARRAY_SIZE(ak1_controller), dev); + break; + + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): + ret = add_controls(rk2_controller, + ARRAY_SIZE(rk2_controller), dev); + break; + + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): + ret = add_controls(rk3_controller, + ARRAY_SIZE(rk3_controller), dev); + break; + + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): + ret = add_controls(kore_controller, + ARRAY_SIZE(kore_controller), dev); + break; + + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): + ret = add_controls(a8dj_controller, + ARRAY_SIZE(a8dj_controller), dev); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): + ret = add_controls(a4dj_controller, + ARRAY_SIZE(a4dj_controller), dev); + break; + } + + return ret; +} + diff --git a/sound/usb/caiaq/control.h b/sound/usb/caiaq/control.h new file mode 100644 index 0000000..2e7ab1a --- /dev/null +++ b/sound/usb/caiaq/control.h @@ -0,0 +1,6 @@ +#ifndef CAIAQ_CONTROL_H +#define CAIAQ_CONTROL_H + +int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev); + +#endif /* CAIAQ_CONTROL_H */ diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c new file mode 100644 index 0000000..6d51770 --- /dev/null +++ b/sound/usb/caiaq/device.c @@ -0,0 +1,521 @@ +/* + * caiaq.c: ALSA driver for caiaq/NativeInstruments devices + * + * Copyright (c) 2007 Daniel Mack + * Karsten Wiese + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "device.h" +#include "audio.h" +#include "midi.h" +#include "control.h" +#include "input.h" + +MODULE_AUTHOR("Daniel Mack "); +MODULE_DESCRIPTION("caiaq USB audio, version 1.3.13"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," + "{Native Instruments, RigKontrol3}," + "{Native Instruments, Kore Controller}," + "{Native Instruments, Kore Controller 2}," + "{Native Instruments, Audio Kontrol 1}," + "{Native Instruments, Audio 4 DJ}," + "{Native Instruments, Audio 8 DJ}," + "{Native Instruments, Session I/O}," + "{Native Instruments, GuitarRig mobile}"); + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ +static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ +static int snd_card_used[SNDRV_CARDS]; + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for the caiaq sound device"); +module_param_array(id, charp, NULL, 0444); +MODULE_PARM_DESC(id, "ID string for the caiaq soundcard."); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable the caiaq soundcard."); + +enum { + SAMPLERATE_44100 = 0, + SAMPLERATE_48000 = 1, + SAMPLERATE_96000 = 2, + SAMPLERATE_192000 = 3, + SAMPLERATE_88200 = 4, + SAMPLERATE_INVALID = 0xff +}; + +enum { + DEPTH_NONE = 0, + DEPTH_16 = 1, + DEPTH_24 = 2, + DEPTH_32 = 3 +}; + +static struct usb_device_id snd_usb_id_table[] = { + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_RIGKONTROL2 + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_RIGKONTROL3 + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_KORECONTROLLER + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_KORECONTROLLER2 + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_AK1 + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_AUDIO8DJ + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_SESSIONIO + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_GUITARRIGMOBILE + }, + { + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = USB_VID_NATIVEINSTRUMENTS, + .idProduct = USB_PID_AUDIO4DJ + }, + { /* terminator */ } +}; + +static void usb_ep1_command_reply_dispatch (struct urb* urb) +{ + int ret; + struct snd_usb_caiaqdev *dev = urb->context; + unsigned char *buf = urb->transfer_buffer; + + if (urb->status || !dev) { + log("received EP1 urb->status = %i\n", urb->status); + return; + } + + switch(buf[0]) { + case EP1_CMD_GET_DEVICE_INFO: + memcpy(&dev->spec, buf+1, sizeof(struct caiaq_device_spec)); + dev->spec.fw_version = le16_to_cpu(dev->spec.fw_version); + debug("device spec (firmware %d): audio: %d in, %d out, " + "MIDI: %d in, %d out, data alignment %d\n", + dev->spec.fw_version, + dev->spec.num_analog_audio_in, + dev->spec.num_analog_audio_out, + dev->spec.num_midi_in, + dev->spec.num_midi_out, + dev->spec.data_alignment); + + dev->spec_received++; + wake_up(&dev->ep1_wait_queue); + break; + case EP1_CMD_AUDIO_PARAMS: + dev->audio_parm_answer = buf[1]; + wake_up(&dev->ep1_wait_queue); + break; + case EP1_CMD_MIDI_READ: + snd_usb_caiaq_midi_handle_input(dev, buf[1], buf + 3, buf[2]); + break; + case EP1_CMD_READ_IO: + if (dev->chip.usb_id == + USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)) { + if (urb->actual_length > sizeof(dev->control_state)) + urb->actual_length = sizeof(dev->control_state); + memcpy(dev->control_state, buf + 1, urb->actual_length); + wake_up(&dev->ep1_wait_queue); + break; + } +#ifdef CONFIG_SND_USB_CAIAQ_INPUT + case EP1_CMD_READ_ERP: + case EP1_CMD_READ_ANALOG: + snd_usb_caiaq_input_dispatch(dev, buf, urb->actual_length); +#endif + break; + } + + dev->ep1_in_urb.actual_length = 0; + ret = usb_submit_urb(&dev->ep1_in_urb, GFP_ATOMIC); + if (ret < 0) + log("unable to submit urb. OOM!?\n"); +} + +int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *dev, + unsigned char command, + const unsigned char *buffer, + int len) +{ + int actual_len; + struct usb_device *usb_dev = dev->chip.dev; + + if (!usb_dev) + return -EIO; + + if (len > EP1_BUFSIZE - 1) + len = EP1_BUFSIZE - 1; + + if (buffer && len > 0) + memcpy(dev->ep1_out_buf+1, buffer, len); + + dev->ep1_out_buf[0] = command; + return usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, 1), + dev->ep1_out_buf, len+1, &actual_len, 200); +} + +int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, + int rate, int depth, int bpp) +{ + int ret; + char tmp[5]; + + switch (rate) { + case 44100: tmp[0] = SAMPLERATE_44100; break; + case 48000: tmp[0] = SAMPLERATE_48000; break; + case 88200: tmp[0] = SAMPLERATE_88200; break; + case 96000: tmp[0] = SAMPLERATE_96000; break; + case 192000: tmp[0] = SAMPLERATE_192000; break; + default: return -EINVAL; + } + + switch (depth) { + case 16: tmp[1] = DEPTH_16; break; + case 24: tmp[1] = DEPTH_24; break; + default: return -EINVAL; + } + + tmp[2] = bpp & 0xff; + tmp[3] = bpp >> 8; + tmp[4] = 1; /* packets per microframe */ + + debug("setting audio params: %d Hz, %d bits, %d bpp\n", + rate, depth, bpp); + + dev->audio_parm_answer = -1; + ret = snd_usb_caiaq_send_command(dev, EP1_CMD_AUDIO_PARAMS, + tmp, sizeof(tmp)); + + if (ret) + return ret; + + if (!wait_event_timeout(dev->ep1_wait_queue, + dev->audio_parm_answer >= 0, HZ)) + return -EPIPE; + + if (dev->audio_parm_answer != 1) + debug("unable to set the device's audio params\n"); + else + dev->bpp = bpp; + + return dev->audio_parm_answer == 1 ? 0 : -EINVAL; +} + +int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, + int digital, int analog, int erp) +{ + char tmp[3] = { digital, analog, erp }; + return snd_usb_caiaq_send_command(dev, EP1_CMD_AUTO_MSG, + tmp, sizeof(tmp)); +} + +static void __devinit setup_card(struct snd_usb_caiaqdev *dev) +{ + int ret; + char val[4]; + + /* device-specific startup specials */ + switch (dev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): + /* RigKontrol2 - display centered dash ('-') */ + val[0] = 0x00; + val[1] = 0x00; + val[2] = 0x01; + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 3); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): + /* RigKontrol2 - display two centered dashes ('--') */ + val[0] = 0x00; + val[1] = 0x40; + val[2] = 0x40; + val[3] = 0x00; + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 4); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): + /* Audio Kontrol 1 - make USB-LED stop blinking */ + val[0] = 0x00; + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 1); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): + /* Audio 8 DJ - trigger read of current settings */ + dev->control_state[0] = 0xff; + snd_usb_caiaq_set_auto_msg(dev, 1, 0, 0); + snd_usb_caiaq_send_command(dev, EP1_CMD_READ_IO, NULL, 0); + + if (!wait_event_timeout(dev->ep1_wait_queue, + dev->control_state[0] != 0xff, HZ)) + return; + + /* fix up some defaults */ + if ((dev->control_state[1] != 2) || + (dev->control_state[2] != 3) || + (dev->control_state[4] != 2)) { + dev->control_state[1] = 2; + dev->control_state[2] = 3; + dev->control_state[4] = 2; + snd_usb_caiaq_send_command(dev, + EP1_CMD_WRITE_IO, dev->control_state, 6); + } + + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): + /* Audio 4 DJ - default input mode to phono */ + dev->control_state[0] = 2; + snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, + dev->control_state, 1); + break; + } + + if (dev->spec.num_analog_audio_out + + dev->spec.num_analog_audio_in + + dev->spec.num_digital_audio_out + + dev->spec.num_digital_audio_in > 0) { + ret = snd_usb_caiaq_audio_init(dev); + if (ret < 0) + log("Unable to set up audio system (ret=%d)\n", ret); + } + + if (dev->spec.num_midi_in + + dev->spec.num_midi_out > 0) { + ret = snd_usb_caiaq_midi_init(dev); + if (ret < 0) + log("Unable to set up MIDI system (ret=%d)\n", ret); + } + +#ifdef CONFIG_SND_USB_CAIAQ_INPUT + ret = snd_usb_caiaq_input_init(dev); + if (ret < 0) + log("Unable to set up input system (ret=%d)\n", ret); +#endif + + /* finally, register the card and all its sub-instances */ + ret = snd_card_register(dev->chip.card); + if (ret < 0) { + log("snd_card_register() returned %d\n", ret); + snd_card_free(dev->chip.card); + } + + ret = snd_usb_caiaq_control_init(dev); + if (ret < 0) + log("Unable to set up control system (ret=%d)\n", ret); +} + +static int create_card(struct usb_device* usb_dev, struct snd_card **cardp) +{ + int devnum; + int err; + struct snd_card *card; + struct snd_usb_caiaqdev *dev; + + for (devnum = 0; devnum < SNDRV_CARDS; devnum++) + if (enable[devnum] && !snd_card_used[devnum]) + break; + + if (devnum >= SNDRV_CARDS) + return -ENODEV; + + err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, + sizeof(struct snd_usb_caiaqdev), &card); + if (err < 0) + return err; + + dev = caiaqdev(card); + dev->chip.dev = usb_dev; + dev->chip.card = card; + dev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor), + le16_to_cpu(usb_dev->descriptor.idProduct)); + spin_lock_init(&dev->spinlock); + snd_card_set_dev(card, &usb_dev->dev); + + *cardp = card; + return 0; +} + +static int __devinit init_card(struct snd_usb_caiaqdev *dev) +{ + char *c; + struct usb_device *usb_dev = dev->chip.dev; + struct snd_card *card = dev->chip.card; + int err, len; + + if (usb_set_interface(usb_dev, 0, 1) != 0) { + log("can't set alt interface.\n"); + return -EIO; + } + + usb_init_urb(&dev->ep1_in_urb); + usb_init_urb(&dev->midi_out_urb); + + usb_fill_bulk_urb(&dev->ep1_in_urb, usb_dev, + usb_rcvbulkpipe(usb_dev, 0x1), + dev->ep1_in_buf, EP1_BUFSIZE, + usb_ep1_command_reply_dispatch, dev); + + usb_fill_bulk_urb(&dev->midi_out_urb, usb_dev, + usb_sndbulkpipe(usb_dev, 0x1), + dev->midi_out_buf, EP1_BUFSIZE, + snd_usb_caiaq_midi_output_done, dev); + + init_waitqueue_head(&dev->ep1_wait_queue); + init_waitqueue_head(&dev->prepare_wait_queue); + + if (usb_submit_urb(&dev->ep1_in_urb, GFP_KERNEL) != 0) + return -EIO; + + err = snd_usb_caiaq_send_command(dev, EP1_CMD_GET_DEVICE_INFO, NULL, 0); + if (err) + return err; + + if (!wait_event_timeout(dev->ep1_wait_queue, dev->spec_received, HZ)) + return -ENODEV; + + usb_string(usb_dev, usb_dev->descriptor.iManufacturer, + dev->vendor_name, CAIAQ_USB_STR_LEN); + + usb_string(usb_dev, usb_dev->descriptor.iProduct, + dev->product_name, CAIAQ_USB_STR_LEN); + + usb_string(usb_dev, usb_dev->descriptor.iSerialNumber, + dev->serial, CAIAQ_USB_STR_LEN); + + /* terminate serial string at first white space occurence */ + c = strchr(dev->serial, ' '); + if (c) + *c = '\0'; + + strcpy(card->driver, MODNAME); + strcpy(card->shortname, dev->product_name); + + len = snprintf(card->longname, sizeof(card->longname), + "%s %s (serial %s, ", + dev->vendor_name, dev->product_name, dev->serial); + + if (len < sizeof(card->longname) - 2) + len += usb_make_path(usb_dev, card->longname + len, + sizeof(card->longname) - len); + + card->longname[len++] = ')'; + card->longname[len] = '\0'; + setup_card(dev); + return 0; +} + +static int __devinit snd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret; + struct snd_card *card; + struct usb_device *device = interface_to_usbdev(intf); + + ret = create_card(device, &card); + + if (ret < 0) + return ret; + + usb_set_intfdata(intf, card); + ret = init_card(caiaqdev(card)); + if (ret < 0) { + log("unable to init card! (ret=%d)\n", ret); + snd_card_free(card); + return ret; + } + + return 0; +} + +static void snd_disconnect(struct usb_interface *intf) +{ + struct snd_usb_caiaqdev *dev; + struct snd_card *card = usb_get_intfdata(intf); + + debug("%s(%p)\n", __func__, intf); + + if (!card) + return; + + dev = caiaqdev(card); + snd_card_disconnect(card); + +#ifdef CONFIG_SND_USB_CAIAQ_INPUT + snd_usb_caiaq_input_free(dev); +#endif + snd_usb_caiaq_audio_free(dev); + + usb_kill_urb(&dev->ep1_in_urb); + usb_kill_urb(&dev->midi_out_urb); + + snd_card_free(card); + usb_reset_device(interface_to_usbdev(intf)); +} + + +MODULE_DEVICE_TABLE(usb, snd_usb_id_table); +static struct usb_driver snd_usb_driver = { + .name = MODNAME, + .probe = snd_probe, + .disconnect = snd_disconnect, + .id_table = snd_usb_id_table, +}; + +static int __init snd_module_init(void) +{ + return usb_register(&snd_usb_driver); +} + +static void __exit snd_module_exit(void) +{ + usb_deregister(&snd_usb_driver); +} + +module_init(snd_module_init) +module_exit(snd_module_exit) + diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h new file mode 100644 index 0000000..4cce1ad --- /dev/null +++ b/sound/usb/caiaq/device.h @@ -0,0 +1,131 @@ +#ifndef CAIAQ_DEVICE_H +#define CAIAQ_DEVICE_H + +#include "../usbaudio.h" + +#define USB_VID_NATIVEINSTRUMENTS 0x17cc + +#define USB_PID_RIGKONTROL2 0x1969 +#define USB_PID_RIGKONTROL3 0x1940 +#define USB_PID_KORECONTROLLER 0x4711 +#define USB_PID_KORECONTROLLER2 0x4712 +#define USB_PID_AK1 0x0815 +#define USB_PID_AUDIO4DJ 0x0839 +#define USB_PID_AUDIO8DJ 0x1978 +#define USB_PID_SESSIONIO 0x1915 +#define USB_PID_GUITARRIGMOBILE 0x0d8d + +#define EP1_BUFSIZE 64 +#define CAIAQ_USB_STR_LEN 0xff +#define MAX_STREAMS 32 + +//#define SND_USB_CAIAQ_DEBUG + +#define MODNAME "snd-usb-caiaq" +#define log(x...) snd_printk(KERN_WARNING MODNAME" log: " x) + +#ifdef SND_USB_CAIAQ_DEBUG +#define debug(x...) snd_printk(KERN_WARNING MODNAME " debug: " x) +#else +#define debug(x...) do { } while(0) +#endif + +#define EP1_CMD_GET_DEVICE_INFO 0x1 +#define EP1_CMD_READ_ERP 0x2 +#define EP1_CMD_READ_ANALOG 0x3 +#define EP1_CMD_READ_IO 0x4 +#define EP1_CMD_WRITE_IO 0x5 +#define EP1_CMD_MIDI_READ 0x6 +#define EP1_CMD_MIDI_WRITE 0x7 +#define EP1_CMD_AUDIO_PARAMS 0x9 +#define EP1_CMD_AUTO_MSG 0xb +#define EP1_CMD_DIMM_LEDS 0xc + +struct caiaq_device_spec { + unsigned short fw_version; + unsigned char hw_subtype; + unsigned char num_erp; + unsigned char num_analog_in; + unsigned char num_digital_in; + unsigned char num_digital_out; + unsigned char num_analog_audio_out; + unsigned char num_analog_audio_in; + unsigned char num_digital_audio_out; + unsigned char num_digital_audio_in; + unsigned char num_midi_out; + unsigned char num_midi_in; + unsigned char data_alignment; +} __attribute__ ((packed)); + +struct snd_usb_caiaq_cb_info; + +struct snd_usb_caiaqdev { + struct snd_usb_audio chip; + + struct urb ep1_in_urb; + struct urb midi_out_urb; + struct urb **data_urbs_in; + struct urb **data_urbs_out; + struct snd_usb_caiaq_cb_info *data_cb_info; + + unsigned char ep1_in_buf[EP1_BUFSIZE]; + unsigned char ep1_out_buf[EP1_BUFSIZE]; + unsigned char midi_out_buf[EP1_BUFSIZE]; + + struct caiaq_device_spec spec; + spinlock_t spinlock; + wait_queue_head_t ep1_wait_queue; + wait_queue_head_t prepare_wait_queue; + int spec_received, audio_parm_answer; + int midi_out_active; + + char vendor_name[CAIAQ_USB_STR_LEN]; + char product_name[CAIAQ_USB_STR_LEN]; + char serial[CAIAQ_USB_STR_LEN]; + + int n_streams, n_audio_in, n_audio_out; + int streaming, first_packet, output_running; + int audio_in_buf_pos[MAX_STREAMS]; + int audio_out_buf_pos[MAX_STREAMS]; + int period_in_count[MAX_STREAMS]; + int period_out_count[MAX_STREAMS]; + int input_panic, output_panic, warned; + char *audio_in_buf, *audio_out_buf; + unsigned int samplerates, bpp; + + struct snd_pcm_substream *sub_playback[MAX_STREAMS]; + struct snd_pcm_substream *sub_capture[MAX_STREAMS]; + + /* Controls */ + unsigned char control_state[64]; + + /* Linux input */ +#ifdef CONFIG_SND_USB_CAIAQ_INPUT + struct input_dev *input_dev; + char phys[64]; /* physical device path */ + unsigned short keycode[64]; +#endif + + /* ALSA */ + struct snd_pcm *pcm; + struct snd_pcm_hardware pcm_info; + struct snd_rawmidi *rmidi; + struct snd_rawmidi_substream *midi_receive_substream; + struct snd_rawmidi_substream *midi_out_substream; +}; + +struct snd_usb_caiaq_cb_info { + struct snd_usb_caiaqdev *dev; + int index; +}; + +#define caiaqdev(c) ((struct snd_usb_caiaqdev*)(c)->private_data) + +int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, int rate, int depth, int bbp); +int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, int digital, int analog, int erp); +int snd_usb_caiaq_send_command(struct snd_usb_caiaqdev *dev, + unsigned char command, + const unsigned char *buffer, + int len); + +#endif /* CAIAQ_DEVICE_H */ diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c new file mode 100644 index 0000000..a48d309 --- /dev/null +++ b/sound/usb/caiaq/input.c @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2006,2007 Daniel Mack, Tim Ruetz + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +#include "device.h" +#include "input.h" + +static unsigned short keycode_ak1[] = { KEY_C, KEY_B, KEY_A }; +static unsigned short keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4, + KEY_5, KEY_6, KEY_7 }; +static unsigned short keycode_rk3[] = { KEY_1, KEY_2, KEY_3, KEY_4, + KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 }; + +static unsigned short keycode_kore[] = { + KEY_FN_F1, /* "menu" */ + KEY_FN_F7, /* "lcd backlight */ + KEY_FN_F2, /* "control" */ + KEY_FN_F3, /* "enter" */ + KEY_FN_F4, /* "view" */ + KEY_FN_F5, /* "esc" */ + KEY_FN_F6, /* "sound" */ + KEY_FN_F8, /* array spacer, never triggered. */ + KEY_RIGHT, + KEY_DOWN, + KEY_UP, + KEY_LEFT, + KEY_SOUND, /* "listen" */ + KEY_RECORD, + KEY_PLAYPAUSE, + KEY_STOP, + BTN_4, /* 8 softkeys */ + BTN_3, + BTN_2, + BTN_1, + BTN_8, + BTN_7, + BTN_6, + BTN_5, + KEY_BRL_DOT4, /* touch sensitive knobs */ + KEY_BRL_DOT3, + KEY_BRL_DOT2, + KEY_BRL_DOT1, + KEY_BRL_DOT8, + KEY_BRL_DOT7, + KEY_BRL_DOT6, + KEY_BRL_DOT5 +}; + +#define DEG90 (range / 2) +#define DEG180 (range) +#define DEG270 (DEG90 + DEG180) +#define DEG360 (DEG180 * 2) +#define HIGH_PEAK (268) +#define LOW_PEAK (-7) + +/* some of these devices have endless rotation potentiometers + * built in which use two tapers, 90 degrees phase shifted. + * this algorithm decodes them to one single value, ranging + * from 0 to 999 */ +static unsigned int decode_erp(unsigned char a, unsigned char b) +{ + int weight_a, weight_b; + int pos_a, pos_b; + int ret; + int range = HIGH_PEAK - LOW_PEAK; + int mid_value = (HIGH_PEAK + LOW_PEAK) / 2; + + weight_b = abs(mid_value - a) - (range / 2 - 100) / 2; + + if (weight_b < 0) + weight_b = 0; + + if (weight_b > 100) + weight_b = 100; + + weight_a = 100 - weight_b; + + if (a < mid_value) { + /* 0..90 and 270..360 degrees */ + pos_b = b - LOW_PEAK + DEG270; + if (pos_b >= DEG360) + pos_b -= DEG360; + } else + /* 90..270 degrees */ + pos_b = HIGH_PEAK - b + DEG90; + + + if (b > mid_value) + /* 0..180 degrees */ + pos_a = a - LOW_PEAK; + else + /* 180..360 degrees */ + pos_a = HIGH_PEAK - a + DEG180; + + /* interpolate both slider values, depending on weight factors */ + /* 0..99 x DEG360 */ + ret = pos_a * weight_a + pos_b * weight_b; + + /* normalize to 0..999 */ + ret *= 10; + ret /= DEG360; + + if (ret < 0) + ret += 1000; + + if (ret >= 1000) + ret -= 1000; + + return ret; +} + +#undef DEG90 +#undef DEG180 +#undef DEG270 +#undef DEG360 +#undef HIGH_PEAK +#undef LOW_PEAK + + +static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev, + const unsigned char *buf, + unsigned int len) +{ + struct input_dev *input_dev = dev->input_dev; + + switch (dev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): + input_report_abs(input_dev, ABS_X, (buf[4] << 8) | buf[5]); + input_report_abs(input_dev, ABS_Y, (buf[0] << 8) | buf[1]); + input_report_abs(input_dev, ABS_Z, (buf[2] << 8) | buf[3]); + input_sync(input_dev); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): + input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]); + input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]); + input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]); + input_sync(input_dev); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): + input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]); + input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]); + input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]); + input_sync(input_dev); + break; + } +} + +static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev, + const char *buf, unsigned int len) +{ + struct input_dev *input_dev = dev->input_dev; + int i; + + switch (dev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): + i = decode_erp(buf[0], buf[1]); + input_report_abs(input_dev, ABS_X, i); + input_sync(input_dev); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): + i = decode_erp(buf[7], buf[5]); + input_report_abs(input_dev, ABS_HAT0X, i); + i = decode_erp(buf[12], buf[14]); + input_report_abs(input_dev, ABS_HAT0Y, i); + i = decode_erp(buf[15], buf[13]); + input_report_abs(input_dev, ABS_HAT1X, i); + i = decode_erp(buf[0], buf[2]); + input_report_abs(input_dev, ABS_HAT1Y, i); + i = decode_erp(buf[3], buf[1]); + input_report_abs(input_dev, ABS_HAT2X, i); + i = decode_erp(buf[8], buf[10]); + input_report_abs(input_dev, ABS_HAT2Y, i); + i = decode_erp(buf[11], buf[9]); + input_report_abs(input_dev, ABS_HAT3X, i); + i = decode_erp(buf[4], buf[6]); + input_report_abs(input_dev, ABS_HAT3Y, i); + input_sync(input_dev); + break; + } +} + +static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev, + char *buf, unsigned int len) +{ + struct input_dev *input_dev = dev->input_dev; + unsigned short *keycode = input_dev->keycode; + int i; + + if (!keycode) + return; + + if (input_dev->id.product == USB_PID_RIGKONTROL2) + for (i = 0; i < len; i++) + buf[i] = ~buf[i]; + + for (i = 0; i < input_dev->keycodemax && i < len * 8; i++) + input_report_key(input_dev, keycode[i], + buf[i / 8] & (1 << (i % 8))); + + if (dev->chip.usb_id == + USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER) || + dev->chip.usb_id == + USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2)) + input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]); + + input_sync(input_dev); +} + +void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, + char *buf, + unsigned int len) +{ + if (!dev->input_dev || len < 1) + return; + + switch (buf[0]) { + case EP1_CMD_READ_ANALOG: + snd_caiaq_input_read_analog(dev, buf + 1, len - 1); + break; + case EP1_CMD_READ_ERP: + snd_caiaq_input_read_erp(dev, buf + 1, len - 1); + break; + case EP1_CMD_READ_IO: + snd_caiaq_input_read_io(dev, buf + 1, len - 1); + break; + } +} + +int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev) +{ + struct usb_device *usb_dev = dev->chip.dev; + struct input_dev *input; + int i, ret; + + input = input_allocate_device(); + if (!input) + return -ENOMEM; + + usb_make_path(usb_dev, dev->phys, sizeof(dev->phys)); + strlcat(dev->phys, "/input0", sizeof(dev->phys)); + + input->name = dev->product_name; + input->phys = dev->phys; + usb_to_input_id(usb_dev, &input->id); + input->dev.parent = &usb_dev->dev; + + switch (dev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): + input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | + BIT_MASK(ABS_Z); + BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk2)); + memcpy(dev->keycode, keycode_rk2, sizeof(keycode_rk2)); + input->keycodemax = ARRAY_SIZE(keycode_rk2); + input_set_abs_params(input, ABS_X, 0, 4096, 0, 10); + input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10); + input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10); + snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): + input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | + BIT_MASK(ABS_Z); + BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_rk3)); + memcpy(dev->keycode, keycode_rk3, sizeof(keycode_rk3)); + input->keycodemax = ARRAY_SIZE(keycode_rk3); + input_set_abs_params(input, ABS_X, 0, 1024, 0, 10); + input_set_abs_params(input, ABS_Y, 0, 1024, 0, 10); + input_set_abs_params(input, ABS_Z, 0, 1024, 0, 10); + snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): + input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input->absbit[0] = BIT_MASK(ABS_X); + BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_ak1)); + memcpy(dev->keycode, keycode_ak1, sizeof(keycode_ak1)); + input->keycodemax = ARRAY_SIZE(keycode_ak1); + input_set_abs_params(input, ABS_X, 0, 999, 0, 10); + snd_usb_caiaq_set_auto_msg(dev, 1, 0, 5); + break; + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): + input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) | + BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) | + BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) | + BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) | + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | + BIT_MASK(ABS_Z); + input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); + BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_kore)); + memcpy(dev->keycode, keycode_kore, sizeof(keycode_kore)); + input->keycodemax = ARRAY_SIZE(keycode_kore); + input_set_abs_params(input, ABS_HAT0X, 0, 999, 0, 10); + input_set_abs_params(input, ABS_HAT0Y, 0, 999, 0, 10); + input_set_abs_params(input, ABS_HAT1X, 0, 999, 0, 10); + input_set_abs_params(input, ABS_HAT1Y, 0, 999, 0, 10); + input_set_abs_params(input, ABS_HAT2X, 0, 999, 0, 10); + input_set_abs_params(input, ABS_HAT2Y, 0, 999, 0, 10); + input_set_abs_params(input, ABS_HAT3X, 0, 999, 0, 10); + input_set_abs_params(input, ABS_HAT3Y, 0, 999, 0, 10); + input_set_abs_params(input, ABS_X, 0, 4096, 0, 10); + input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10); + input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10); + input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1); + snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5); + break; + default: + /* no input methods supported on this device */ + input_free_device(input); + return 0; + } + + input->keycode = dev->keycode; + input->keycodesize = sizeof(unsigned short); + for (i = 0; i < input->keycodemax; i++) + __set_bit(dev->keycode[i], input->keybit); + + ret = input_register_device(input); + if (ret < 0) { + input_free_device(input); + return ret; + } + + dev->input_dev = input; + return 0; +} + +void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev) +{ + if (!dev || !dev->input_dev) + return; + + input_unregister_device(dev->input_dev); + dev->input_dev = NULL; +} + diff --git a/sound/usb/caiaq/input.h b/sound/usb/caiaq/input.h new file mode 100644 index 0000000..ced5355 --- /dev/null +++ b/sound/usb/caiaq/input.h @@ -0,0 +1,8 @@ +#ifndef CAIAQ_INPUT_H +#define CAIAQ_INPUT_H + +void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, char *buf, unsigned int len); +int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev); +void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev); + +#endif diff --git a/sound/usb/caiaq/midi.c b/sound/usb/caiaq/midi.c new file mode 100644 index 0000000..8fa8cd8 --- /dev/null +++ b/sound/usb/caiaq/midi.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2006,2007 Daniel Mack + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +#include "device.h" +#include "midi.h" + +static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) +{ + struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; + + if (!dev) + return; + + dev->midi_receive_substream = up ? substream : NULL; +} + + +static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substream) +{ + return 0; +} + +static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream) +{ + struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; + if (dev->midi_out_active) { + usb_kill_urb(&dev->midi_out_urb); + dev->midi_out_active = 0; + } + return 0; +} + +static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev, + struct snd_rawmidi_substream *substream) +{ + int len, ret; + + dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE; + dev->midi_out_buf[1] = 0; /* port */ + len = snd_rawmidi_transmit(substream, dev->midi_out_buf + 3, + EP1_BUFSIZE - 3); + + if (len <= 0) + return; + + dev->midi_out_buf[2] = len; + dev->midi_out_urb.transfer_buffer_length = len+3; + + ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC); + if (ret < 0) + log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed," + "ret=%d, len=%d\n", + substream, ret, len); + else + dev->midi_out_active = 1; +} + +static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) +{ + struct snd_usb_caiaqdev *dev = substream->rmidi->private_data; + + if (up) { + dev->midi_out_substream = substream; + if (!dev->midi_out_active) + snd_usb_caiaq_midi_send(dev, substream); + } else { + dev->midi_out_substream = NULL; + } +} + + +static struct snd_rawmidi_ops snd_usb_caiaq_midi_output = +{ + .open = snd_usb_caiaq_midi_output_open, + .close = snd_usb_caiaq_midi_output_close, + .trigger = snd_usb_caiaq_midi_output_trigger, +}; + +static struct snd_rawmidi_ops snd_usb_caiaq_midi_input = +{ + .open = snd_usb_caiaq_midi_input_open, + .close = snd_usb_caiaq_midi_input_close, + .trigger = snd_usb_caiaq_midi_input_trigger, +}; + +void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, + int port, const char *buf, int len) +{ + if (!dev->midi_receive_substream) + return; + + snd_rawmidi_receive(dev->midi_receive_substream, buf, len); +} + +int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device) +{ + int ret; + struct snd_rawmidi *rmidi; + + ret = snd_rawmidi_new(device->chip.card, device->product_name, 0, + device->spec.num_midi_out, + device->spec.num_midi_in, + &rmidi); + + if (ret < 0) + return ret; + + strcpy(rmidi->name, device->product_name); + + rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX; + rmidi->private_data = device; + + if (device->spec.num_midi_out > 0) { + rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, + &snd_usb_caiaq_midi_output); + } + + if (device->spec.num_midi_in > 0) { + rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; + snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, + &snd_usb_caiaq_midi_input); + } + + device->rmidi = rmidi; + + return 0; +} + +void snd_usb_caiaq_midi_output_done(struct urb* urb) +{ + struct snd_usb_caiaqdev *dev = urb->context; + + dev->midi_out_active = 0; + if (urb->status != 0) + return; + + if (!dev->midi_out_substream) + return; + + snd_usb_caiaq_midi_send(dev, dev->midi_out_substream); +} + diff --git a/sound/usb/caiaq/midi.h b/sound/usb/caiaq/midi.h new file mode 100644 index 0000000..9d16db0 --- /dev/null +++ b/sound/usb/caiaq/midi.h @@ -0,0 +1,8 @@ +#ifndef CAIAQ_MIDI_H +#define CAIAQ_MIDI_H + +int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev); +void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len); +void snd_usb_caiaq_midi_output_done(struct urb* urb); + +#endif /* CAIAQ_MIDI_H */ -- cgit v1.1 From 9d59065cd6fae841ca56c281189d5b8d0817d35f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2009 16:13:58 +0200 Subject: ALSA: add private_data to struct snd_jack Added private_data and private_free fields to struct snd_jack so that the caller can assign the data. It'll be helpful for avoiding the double-free of the jack instance. Signed-off-by: Takashi Iwai --- sound/core/jack.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/core/jack.c b/sound/core/jack.c index c8254c6..d54d1a0 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -35,6 +35,9 @@ static int snd_jack_dev_free(struct snd_device *device) { struct snd_jack *jack = device->device_data; + if (jack->private_free) + jack->private_free(jack); + /* If the input device is registered with the input subsystem * then we need to use a different deallocator. */ if (jack->registered) -- cgit v1.1 From 95c0909961bc5ff18c78b2ab0d093cddc0a8b0b5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2009 16:15:29 +0200 Subject: ALSA: hda - Avoid call of snd_jack_report at release Don't call snd_jack_report at release of sigmatel and conexnat codecs which results in Oops at unloading the module. The Oops is triggered by the power-up sequence during the free due to the pincfg restoration. Since the power-up sequence is involved with the unsol handling, the jack reporting may be issued during that. The Oops occurs with this jack reporting because the jack instances have been already released but the codec doesn't do the proper book-keeping. This patch adds the book-keeping of jack instances to avoid the access to bogus pointers. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_conexant.c | 21 ++++++++++++++++++--- sound/pci/hda/patch_sigmatel.c | 27 ++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 1f2ad76..56ce19e 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -350,12 +350,20 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, } #ifdef CONFIG_SND_JACK +static void conexant_free_jack_priv(struct snd_jack *jack) +{ + struct conexant_jack *jacks = jack->private_data; + jacks->nid = 0; + jacks->jack = NULL; +} + static int conexant_add_jack(struct hda_codec *codec, hda_nid_t nid, int type) { struct conexant_spec *spec; struct conexant_jack *jack; const char *name; + int err; spec = codec->spec; snd_array_init(&spec->jacks, sizeof(*jack), 32); @@ -368,7 +376,12 @@ static int conexant_add_jack(struct hda_codec *codec, jack->nid = nid; jack->type = type; - return snd_jack_new(codec->bus->card, name, type, &jack->jack); + err = snd_jack_new(codec->bus->card, name, type, &jack->jack); + if (err < 0) + return err; + jack->jack->private_data = jack; + jack->jack->private_free = conexant_free_jack_priv; + return 0; } static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) @@ -455,8 +468,10 @@ static void conexant_free(struct hda_codec *codec) if (spec->jacks.list) { struct conexant_jack *jacks = spec->jacks.list; int i; - for (i = 0; i < spec->jacks.used; i++) - snd_device_free(codec->bus->card, &jacks[i].jack); + for (i = 0; i < spec->jacks.used; i++, jacks++) { + if (jacks->jack) + snd_device_free(codec->bus->card, jacks->jack); + } snd_array_free(&spec->jacks); } #endif diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 61996a2..ce30b45 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -3851,6 +3851,15 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ } +#ifdef CONFIG_SND_JACK +static void stac92xx_free_jack_priv(struct snd_jack *jack) +{ + struct sigmatel_jack *jacks = jack->private_data; + jacks->nid = 0; + jacks->jack = NULL; +} +#endif + static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type) { @@ -3860,6 +3869,7 @@ static int stac92xx_add_jack(struct hda_codec *codec, int def_conf = snd_hda_codec_get_pincfg(codec, nid); int connectivity = get_defcfg_connect(def_conf); char name[32]; + int err; if (connectivity && connectivity != AC_JACK_PORT_FIXED) return 0; @@ -3876,10 +3886,15 @@ static int stac92xx_add_jack(struct hda_codec *codec, snd_hda_get_jack_connectivity(def_conf), snd_hda_get_jack_location(def_conf)); - return snd_jack_new(codec->bus->card, name, type, &jack->jack); -#else - return 0; + err = snd_jack_new(codec->bus->card, name, type, &jack->jack); + if (err < 0) { + jack->nid = 0; + return err; + } + jack->jack->private_data = jack; + jack->jack->private_free = stac92xx_free_jack_priv; #endif + return 0; } static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid, @@ -4138,8 +4153,10 @@ static void stac92xx_free_jacks(struct hda_codec *codec) if (!codec->bus->shutdown && spec->jacks.list) { struct sigmatel_jack *jacks = spec->jacks.list; int i; - for (i = 0; i < spec->jacks.used; i++) - snd_device_free(codec->bus->card, &jacks[i].jack); + for (i = 0; i < spec->jacks.used; i++, jacks++) { + if (jacks->jack) + snd_device_free(codec->bus->card, jacks->jack); + } } snd_array_free(&spec->jacks); #endif -- cgit v1.1 From 29dab4fd3176e25dfab6cd763beb02d87973c288 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 14 Apr 2009 22:40:04 +0200 Subject: [ALSA] intel8x0: fix wrong conditions in ac97_clock measure routine Also add a little code cleanup. Signed-off-by: Jaroslav Kysela --- sound/pci/intel8x0.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 6962f94..10f8609 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2689,7 +2689,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) } ichdev = &chip->ichd[ICHD_PCMOUT]; ichdev->physbuf = subs->dma_buffer.addr; - ichdev->size = chip->ichd[ICHD_PCMOUT].fragsize = INTEL8X0_TESTBUF_SIZE; + ichdev->size = ichdev->fragsize = INTEL8X0_TESTBUF_SIZE; ichdev->substream = NULL; /* don't process interrupts */ /* set rate */ @@ -2766,10 +2766,10 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) if (pos < 40000 || pos >= 60000) /* abnormal value. hw problem? */ printk(KERN_INFO "intel8x0: measured clock %ld rejected\n", pos); - else if (pos > 40500 || pos < 41500) + else if (pos > 40500 && pos < 41500) /* first exception - 41000Hz reference clock */ chip->ac97_bus->clock = 41000; - else if (pos > 43600 || pos < 44600) + else if (pos > 43600 && pos < 44600) /* second exception - 44100HZ reference clock */ chip->ac97_bus->clock = 44100; else if (pos < 47500 || pos > 48500) -- cgit v1.1 From 5e901b37e4a8a305542ad3a776bce997efd7e5e9 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Thu, 9 Apr 2009 14:07:27 +0800 Subject: [ARM] pxa/magician: remove un-necessary #include of pxa-regs.h and hardware.h Signed-off-by: Eric Miao Cc: Philipp Zabel Cc: Mark Brown --- sound/soc/pxa/magician.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index f7c4544..0625c34 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -27,8 +27,6 @@ #include #include -#include -#include #include #include #include "../codecs/uda1380.h" -- cgit v1.1 From eae17754ab1ffc88190ebcbd33b6bec79e6e559a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 13 Apr 2009 11:48:03 +0100 Subject: [ARM] pxa: merge AC97 platform data structures Currently there are two possible platform datas for the PXA AC97 driver: one supported by the generic AC97 driver only which provides callbacks to allow board-specific configuration at stream startup and teardown, and another for pxa2xx-ac97-lib which allows configuration of the reset GPIO for PXA2xx CPUs. Obviously this won't actually work when using the generic AC97 driver since the drivers will attempt to parse the platform data in both formats. Fix this by merging the two structures. Signed-off-by: Mark Brown Acked-by: Robert Jarzmik Cc: Marek Vasut Signed-off-by: Eric Miao --- sound/arm/pxa2xx-ac97-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 0afd1a8..a2c12d1 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -364,7 +364,7 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) { int ret; - struct pxa2xx_ac97_platform_data *pdata = dev->dev.platform_data; + pxa2xx_audio_ops_t *pdata = dev->dev.platform_data; if (pdata) { switch (pdata->reset_gpio) { -- cgit v1.1 From 2ec775e7053c82bc90858ede011b35aeb416995b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 15 Apr 2009 10:16:24 +0200 Subject: [ALSA] intel8x0: add one retry to the ac97_clock measurement routine It seems that on some hardware platforms, the first measurement is wrong. This patch adds second measurement to this case. Signed-off-by: Jaroslav Kysela --- sound/pci/intel8x0.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 10f8609..5dced5b 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2676,12 +2676,13 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) struct ichdev *ichdev; unsigned long port; unsigned long pos, pos1, t; - int civ, timeout = 1000; + int civ, timeout = 1000, attempt = 1; struct timespec start_time, stop_time; if (chip->ac97_bus->clock != 48000) return; /* specified in module option */ + __again: subs = chip->pcm[0]->streams[0].substream; if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) { snd_printk(KERN_WARNING "no playback buffer allocated - aborting measure ac97 clock\n"); @@ -2749,6 +2750,11 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) if (pos == 0) { snd_printk(KERN_ERR "intel8x0: measure - unreliable DMA position..\n"); + __retry: + if (attempt < 2) { + attempt++; + goto __again; + } return; } @@ -2759,14 +2765,15 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) printk(KERN_INFO "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos); if (t == 0) { snd_printk(KERN_ERR "intel8x0: ?? calculation error..\n"); - return; + goto __retry; } pos *= 1000; pos = (pos / t) * 1000 + ((pos % t) * 1000) / t; - if (pos < 40000 || pos >= 60000) + if (pos < 40000 || pos >= 60000) { /* abnormal value. hw problem? */ printk(KERN_INFO "intel8x0: measured clock %ld rejected\n", pos); - else if (pos > 40500 && pos < 41500) + goto __retry; + } else if (pos > 40500 && pos < 41500) /* first exception - 41000Hz reference clock */ chip->ac97_bus->clock = 41000; else if (pos > 43600 && pos < 44600) -- cgit v1.1 From bfb53037c61ddf7c16a40297ad16f2bcbde534dc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2009 14:51:04 +0200 Subject: ALSA: hda - Add quirk mask for Fujitsu Amilo laptops with ALC883 Added the models for quirk bitmask 1734:110x and 1734:113x of Fujitsu laptops. This will fix the model detection for Amilo Xa3540. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f35e58a..6ed787e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -8742,10 +8742,9 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), - SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550", + SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx", ALC883_FUJITSU_PI2515), - SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515), - SND_PCI_QUIRK(0x1734, 0x113d, "Fujitsu AMILO Xa3530", + SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx", ALC888_FUJITSU_XA3530), SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), -- cgit v1.1 From fcad94a4c71c36a05f4d5c6dcb174534b4e0b136 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 15 Apr 2009 17:48:35 +0200 Subject: ALSA: hda - Fix the cmd cache keys for amp verbs Fix the key value generation for get/set amp verbs. The upper bits of the parameter have to be combined with the verb value to be unique for each direction/index of amp access. This fixes the resume problem on some hardwares like Macbook after the channel mode is changed. Tested-by: Johannes Berg Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index a4e5e59..fd6e6f3 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2250,7 +2250,11 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, err = bus->ops.command(bus, res); if (!err) { struct hda_cache_head *c; - u32 key = build_cmd_cache_key(nid, verb); + u32 key; + /* parm may contain the verb stuff for get/set amp */ + verb = verb | (parm >> 8); + parm &= 0xff; + key = build_cmd_cache_key(nid, verb); c = get_alloc_hash(&codec->cmd_cache, key); if (c) c->val = parm; -- cgit v1.1 From d523b0c808a5c5cbde9ac89427d98ee6288f5f2f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 15 Apr 2009 11:39:01 -0700 Subject: ALSA: hda_intel.c - Consolidate bitfields Commit fa00e046b41663cbda9b1affc0594669e5f14219 added a new bitfield not adjacent to other bitfields in the same struct. Moved the new one. Signed-off-by: Joe Perches Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index bc882f8..21e99cf 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -312,7 +312,6 @@ struct azx_dev { unsigned int period_bytes; /* size of the period in bytes */ unsigned int frags; /* number for period in the play buffer */ unsigned int fifo_size; /* FIFO size */ - unsigned int start_flag: 1; /* stream full start flag */ unsigned long start_jiffies; /* start + minimum jiffies */ unsigned long min_jiffies; /* minimum jiffies before position is valid */ @@ -333,6 +332,7 @@ struct azx_dev { unsigned int opened :1; unsigned int running :1; unsigned int irq_pending :1; + unsigned int start_flag: 1; /* stream full start flag */ /* * For VIA: * A flag to ensure DMA position is 0 -- cgit v1.1 From 4611b043ce9c45cd8ac760b8379b02ceffe26b0d Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Wed, 15 Apr 2009 19:43:35 -0400 Subject: ALSA: Intel8x0: Remove conflicting quirk for SSID 0x103c0934 While cleaning up quirks, I noticed that there is a duplicated quirk for the SSID 0x103c0934. Looking back through the bug reports, I've concluded that there is only one necessary quirk (hp_mute_led), so this patch removes the conflicting one. Reference: Ubuntu #44066 (https://launchpad.net/bugs/44066) Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 5dced5b..b3180d0 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1896,12 +1896,6 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x103c, - .subdevice = 0x0934, - .name = "HP nx8220", - .type = AC97_TUNE_MUTE_LED - }, - { - .subvendor = 0x103c, .subdevice = 0x129d, .name = "HP xw8000", .type = AC97_TUNE_HP_ONLY -- cgit v1.1 From c82834251ceb81b7575927c767500bd8c4a7f928 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Wed, 15 Apr 2009 19:48:08 -0400 Subject: ALSA: Intel8x0: Add hp_only quirk for SSID 0x1028016a (Dell Inspiron 8600) Subject says it all. Briefly, use hp_only for another Dell Inspiron 8600. Reference: Ubuntu #41015 (https://launchpad.net/bugs/41015) Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai --- sound/pci/intel8x0.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index b3180d0..8042d53 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1854,6 +1854,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x1028, + .subdevice = 0x016a, + .name = "Dell Inspiron 8600", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, + { + .subvendor = 0x1028, .subdevice = 0x0186, .name = "Dell Latitude D810", /* cf. Malone #41015 */ .type = AC97_TUNE_HP_MUTE_LED -- cgit v1.1 From ffd0e56c606836581da5df742a43ce8015ca7475 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Apr 2009 12:20:24 +0200 Subject: ALSA: hda - Fix headphone-detection on some machines with STAC/IDT codecs When the headphone can have no unique DAC, the current code doesn't check the HP-detection although it should. Put the hp-detection check before the DAC check to fix this bug. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_sigmatel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index ce30b45..917bc5d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -3076,6 +3076,11 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, unsigned int wid_caps; for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) { + if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) { + wid_caps = get_wcaps(codec, pins[i]); + if (wid_caps & AC_WCAP_UNSOL_CAP) + spec->hp_detect = 1; + } nid = dac_nids[i]; if (!nid) continue; @@ -3119,11 +3124,6 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, err = create_controls_idx(codec, name, idx, nid, 3); if (err < 0) return err; - if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) { - wid_caps = get_wcaps(codec, pins[i]); - if (wid_caps & AC_WCAP_UNSOL_CAP) - spec->hp_detect = 1; - } } } return 0; -- cgit v1.1 From 4dc1f87f079d5c6b01284d08b28eff2c4fbd15c4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 16 Apr 2009 14:19:19 +0200 Subject: ALSA: hda - Add upper-limit of mixer amp for AD1884A-laptop model, too Add the upper-limit of mixer amp for AD1884A-laptop model just like the mobile model for some HP laptops. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 38ad3f7..9bcd8ab 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3977,6 +3977,14 @@ static int patch_ad1884a(struct hda_codec *codec) spec->input_mux = &ad1884a_laptop_capture_source; codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; codec->patch_ops.init = ad1884a_hp_init; + /* set the upper-limit for mixer amp to 0dB for avoiding the + * possible damage by overloading + */ + snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, + (0x17 << AC_AMPCAP_OFFSET_SHIFT) | + (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | + (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | + (1 << AC_AMPCAP_MUTE_SHIFT)); break; case AD1884A_MOBILE: spec->mixers[0] = ad1884a_mobile_mixers; -- cgit v1.1 From 5a47fa3d30b5d1977b4e7d1daf5ba5b577258ce1 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Thu, 16 Apr 2009 23:54:04 +0200 Subject: ALSA: emu10k1 - off by 1 in snd_emu10k1_wait() With `while (count++ < 16384)' count reaches 16385. Signed-off-by: Roel Kluin Signed-off-by: Takashi Iwai --- sound/pci/emu10k1/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index 4bfc31d..c1a5aa1 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c @@ -490,7 +490,7 @@ void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait) if (newtime != curtime) break; } - if (count >= 16384) + if (count > 16384) break; curtime = newtime; } -- cgit v1.1 From f600f6c4824d7e40be370f7e26ab0fbc3f6f911c Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Thu, 16 Apr 2009 19:35:01 +0200 Subject: ALSA: us122l: Fix signedness in comparisions Within 2.6.30's mergewindow, struct urb's transfer_buffer_length has become unsigned. This changed an "int > int" comparision to an "unsigned > int" one in snd_usb_122l. Fix this by using a local int variable instead of urb->transfer_buffer_length in comparisions. Shorten playback_prep_freqn() a bit and tweak error-paths in usb_stream_prepare_playback(). Signed-off-by: Karsten Wiese Signed-off-by: Takashi Iwai --- sound/usb/usx2y/usb_stream.c | 67 ++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 37 deletions(-) (limited to 'sound') diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 24393da..12ae034 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -33,32 +33,26 @@ static unsigned usb_stream_next_packet_size(struct usb_stream_kernel *sk) static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb) { struct usb_stream *s = sk->s; - unsigned l = 0; - int pack; - - urb->iso_frame_desc[0].offset = 0; - urb->iso_frame_desc[0].length = usb_stream_next_packet_size(sk); - sk->out_phase = sk->out_phase_peeked; - urb->transfer_buffer_length = urb->iso_frame_desc[0].length; - - for (pack = 1; pack < sk->n_o_ps; pack++) { - l = usb_stream_next_packet_size(sk); - if (s->idle_outsize + urb->transfer_buffer_length + l > - s->period_size) + int pack, lb = 0; + + for (pack = 0; pack < sk->n_o_ps; pack++) { + int l = usb_stream_next_packet_size(sk); + if (s->idle_outsize + lb + l > s->period_size) goto check; sk->out_phase = sk->out_phase_peeked; - urb->iso_frame_desc[pack].offset = urb->transfer_buffer_length; + urb->iso_frame_desc[pack].offset = lb; urb->iso_frame_desc[pack].length = l; - urb->transfer_buffer_length += l; + lb += l; } - snd_printdd(KERN_DEBUG "%i\n", urb->transfer_buffer_length); + snd_printdd(KERN_DEBUG "%i\n", lb); check: urb->number_of_packets = pack; - s->idle_outsize += urb->transfer_buffer_length - s->period_size; + urb->transfer_buffer_length = lb; + s->idle_outsize += lb - s->period_size; snd_printdd(KERN_DEBUG "idle=%i ul=%i ps=%i\n", s->idle_outsize, - urb->transfer_buffer_length, s->period_size); + lb, s->period_size); } static void init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, @@ -282,21 +276,20 @@ static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, struct usb_stream *s = sk->s; struct urb *io; struct usb_iso_packet_descriptor *id, *od; - int p, l = 0; + int p = 0, lb = 0, l = 0; io = sk->idle_outurb; od = io->iso_frame_desc; - io->transfer_buffer_length = 0; - for (p = 0; s->sync_packet < 0; ++p, ++s->sync_packet) { + for (; s->sync_packet < 0; ++p, ++s->sync_packet) { struct urb *ii = sk->completed_inurb; id = ii->iso_frame_desc + ii->number_of_packets + s->sync_packet; l = id->actual_length; od[p].length = l; - od[p].offset = io->transfer_buffer_length; - io->transfer_buffer_length += l; + od[p].offset = lb; + lb += l; } for (; @@ -304,38 +297,38 @@ static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, ++p, ++s->sync_packet) { l = inurb->iso_frame_desc[s->sync_packet].actual_length; - if (s->idle_outsize + io->transfer_buffer_length + l > - s->period_size) + if (s->idle_outsize + lb + l > s->period_size) goto check_ok; od[p].length = l; - od[p].offset = io->transfer_buffer_length; - io->transfer_buffer_length += l; + od[p].offset = lb; + lb += l; } check_ok: s->sync_packet -= inurb->number_of_packets; - if (s->sync_packet < -2 || s->sync_packet > 0) { + if (unlikely(s->sync_packet < -2 || s->sync_packet > 0)) { snd_printk(KERN_WARNING "invalid sync_packet = %i;" " p=%i nop=%i %i %x %x %x > %x\n", s->sync_packet, p, inurb->number_of_packets, - s->idle_outsize + io->transfer_buffer_length + l, - s->idle_outsize, io->transfer_buffer_length, l, + s->idle_outsize + lb + l, + s->idle_outsize, lb, l, s->period_size); return -1; } - if (io->transfer_buffer_length % s->cfg.frame_size) { + if (unlikely(lb % s->cfg.frame_size)) { snd_printk(KERN_WARNING"invalid outsize = %i\n", - io->transfer_buffer_length); + lb); return -1; } - s->idle_outsize += io->transfer_buffer_length - s->period_size; + s->idle_outsize += lb - s->period_size; io->number_of_packets = p; - if (s->idle_outsize > 0) { - snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize); - return -1; - } - return 0; + io->transfer_buffer_length = lb; + if (s->idle_outsize <= 0) + return 0; + + snd_printk(KERN_WARNING "idle=%i\n", s->idle_outsize); + return -1; } static void prepare_inurb(int number_of_packets, struct urb *iu) -- cgit v1.1 From 93e82ae781e1ca4797cf2a226d3c303975bd99c7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 17 Apr 2009 18:04:41 +0200 Subject: ALSA: hda - Set function_id only on FG nodes (Re)set function_id only from the value on FG nodes. The current code overrides the value with the last widget. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index fd6e6f3..8820faf 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -642,19 +642,21 @@ static int get_codec_name(struct hda_codec *codec) */ static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec) { - int i, total_nodes; + int i, total_nodes, function_id; hda_nid_t nid; total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid); for (i = 0; i < total_nodes; i++, nid++) { - codec->function_id = snd_hda_param_read(codec, nid, + function_id = snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff; - switch (codec->function_id) { + switch (function_id) { case AC_GRP_AUDIO_FUNCTION: codec->afg = nid; + codec->function_id = function_id; break; case AC_GRP_MODEM_FUNCTION: codec->mfg = nid; + codec->function_id = function_id; break; default: break; -- cgit v1.1 From e91fb9137dd235ab959d7675d0e4104974dad5eb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 17 Apr 2009 11:37:35 +0200 Subject: [ARM] pxa/palm27x: General fix for Palm27x aSoC driver Firstly, this patch makes the palm27x asoc driver a little more sane. Also, since all affected devices use GPIO95 as AC97_nRESET, this patch sets that properly. Affected are PalmT5, TX and LifeDrive. Signed-off-by: Marek Vasut Signed-off-by: Eric Miao --- sound/soc/pxa/palm27x.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c index 48a73f6..44fcc4e 100644 --- a/sound/soc/pxa/palm27x.c +++ b/sound/soc/pxa/palm27x.c @@ -200,7 +200,7 @@ static struct snd_soc_device palm27x_snd_devdata = { static struct platform_device *palm27x_snd_device; -static int __init palm27x_asoc_init(void) +static int palm27x_asoc_probe(struct platform_device *pdev) { int ret; @@ -208,6 +208,10 @@ static int __init palm27x_asoc_init(void) machine_is_palmld())) return -ENODEV; + if (pdev->dev.platform_data) + palm27x_ep_gpio = ((struct palm27x_asoc_info *) + (pdev->dev.platform_data))->jack_gpio; + ret = gpio_request(palm27x_ep_gpio, "Headphone Jack"); if (ret) return ret; @@ -245,16 +249,31 @@ err_alloc: return ret; } -static void __exit palm27x_asoc_exit(void) +static int __devexit palm27x_asoc_remove(struct platform_device *pdev) { free_irq(gpio_to_irq(palm27x_ep_gpio), NULL); gpio_free(palm27x_ep_gpio); platform_device_unregister(palm27x_snd_device); + return 0; } -void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data) +static struct platform_driver palm27x_wm9712_driver = { + .probe = palm27x_asoc_probe, + .remove = __devexit_p(palm27x_asoc_remove), + .driver = { + .name = "palm27x-asoc", + .owner = THIS_MODULE, + }, +}; + +static int __init palm27x_asoc_init(void) +{ + return platform_driver_register(&palm27x_wm9712_driver); +} + +static void __exit palm27x_asoc_exit(void) { - palm27x_ep_gpio = data->jack_gpio; + platform_driver_unregister(&palm27x_wm9712_driver); } module_init(palm27x_asoc_init); -- cgit v1.1 From 5d4af1be06affa2b42cdf59cd376752be1f934b3 Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Mon, 20 Apr 2009 13:01:21 +0200 Subject: ALSA: us122l: add snd_us122l_free() Use it to clean up snd_us122l_card_used[]. Without patch unplugging of an US122L soundcard didn't reset the corresponding element of snd_us122l_card_used[] to 0. The (SNDRV_CARDS + 1)th plugging in did not result in creating the soundcard device anymore. Index values supplied with the modprobe command line were not used correctly anymore after the first unplugging of an US122L. Signed-off-by: Karsten Wiese Cc: stable@kernel.org Signed-off-by: Takashi Iwai --- sound/usb/usx2y/us122l.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 98276aa..463f3ff 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -478,6 +478,14 @@ static bool us122l_create_card(struct snd_card *card) return true; } +static void snd_us122l_free(struct snd_card *card) +{ + struct us122l *us122l = US122L(card); + int index = us122l->chip.index; + if (index >= 0 && index < SNDRV_CARDS) + snd_us122l_card_used[index] = 0; +} + static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) { int dev; @@ -494,7 +502,7 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp) if (err < 0) return err; snd_us122l_card_used[US122L(card)->chip.index = dev] = 1; - + card->private_free = snd_us122l_free; US122L(card)->chip.dev = device; US122L(card)->chip.card = card; mutex_init(&US122L(card)->mutex); @@ -588,7 +596,7 @@ static void snd_us122l_disconnect(struct usb_interface *intf) } usb_put_intf(intf); - usb_put_dev(US122L(card)->chip.dev); + usb_put_dev(us122l->chip.dev); while (atomic_read(&us122l->mmap_count)) msleep(500); -- cgit v1.1 From e3ba906ad17330e44fad5af42a423417249c6e09 Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Mon, 20 Apr 2009 07:09:11 -0400 Subject: ALSA: Atiixp: Add SSID for mute_led quirk (unknown HP model) Reference: Ubuntu #84973 (https://launchpad.net/bugs/84973) Reference: Linux #8001 (http://bugzilla.kernel.org/show_bug.cgi?id=8001) Make the mute LED function properly on this unknown HP model. Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai --- sound/pci/atiixp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sound') diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 9ce8548..71515dd 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1393,6 +1393,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "HP nx6125", .type = AC97_TUNE_MUTE_LED }, + { + .subvendor = 0x103c, + .subdevice = 0x3091, + .name = "unknown HP", + .type = AC97_TUNE_MUTE_LED + }, { } /* terminator */ }; -- cgit v1.1 From cfbf1eecd70db9a7a49c42a0613c00f7a2a86dfb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 20 Apr 2009 22:54:25 +0200 Subject: ALSA: AOA: Convert onyx and tas codecs to new-style i2c drivers The legacy i2c binding model is going away soon, so convert the AOA codec drivers to the new model or they'll break. Signed-off-by: Jean Delvare Tested-by: Johannes Berg Tested-by: Andreas Schwab Cc: Benjamin Herrenschmidt Signed-off-by: Takashi Iwai --- sound/aoa/codecs/onyx.c | 76 ++++++++++++++++++++++++++++++++++--------------- sound/aoa/codecs/tas.c | 66 ++++++++++++++++++++++++++---------------- 2 files changed, 95 insertions(+), 47 deletions(-) (limited to 'sound') diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 15500b9..84bb07d 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -47,7 +47,7 @@ MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa"); struct onyx { /* cache registers 65 to 80, they are write-only! */ u8 cache[16]; - struct i2c_client i2c; + struct i2c_client *i2c; struct aoa_codec codec; u32 initialised:1, spdif_locked:1, @@ -72,7 +72,7 @@ static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value) *value = onyx->cache[reg-FIRSTREGISTER]; return 0; } - v = i2c_smbus_read_byte_data(&onyx->i2c, reg); + v = i2c_smbus_read_byte_data(onyx->i2c, reg); if (v < 0) return -1; *value = (u8)v; @@ -84,7 +84,7 @@ static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value) { int result; - result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value); + result = i2c_smbus_write_byte_data(onyx->i2c, reg, value); if (!result) onyx->cache[reg-FIRSTREGISTER] = value; return result; @@ -996,12 +996,45 @@ static void onyx_exit_codec(struct aoa_codec *codec) onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); } -static struct i2c_driver onyx_driver; - static int onyx_create(struct i2c_adapter *adapter, struct device_node *node, int addr) { + struct i2c_board_info info; + struct i2c_client *client; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "aoa_codec_onyx", I2C_NAME_SIZE); + info.addr = addr; + info.platform_data = node; + client = i2c_new_device(adapter, &info); + if (!client) + return -ENODEV; + + /* + * We know the driver is already loaded, so the device should be + * already bound. If not it means binding failed, which suggests + * the device doesn't really exist and should be deleted. + * Ideally this would be replaced by better checks _before_ + * instantiating the device. + */ + if (!client->driver) { + i2c_unregister_device(client); + return -ENODEV; + } + + /* + * Let i2c-core delete that device on driver removal. + * This is safe because i2c-core holds the core_lock mutex for us. + */ + list_add_tail(&client->detected, &client->driver->clients); + return 0; +} + +static int onyx_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device_node *node = client->dev.platform_data; struct onyx *onyx; u8 dummy; @@ -1011,20 +1044,12 @@ static int onyx_create(struct i2c_adapter *adapter, return -ENOMEM; mutex_init(&onyx->mutex); - onyx->i2c.driver = &onyx_driver; - onyx->i2c.adapter = adapter; - onyx->i2c.addr = addr & 0x7f; - strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE); - - if (i2c_attach_client(&onyx->i2c)) { - printk(KERN_ERR PFX "failed to attach to i2c\n"); - goto fail; - } + onyx->i2c = client; + i2c_set_clientdata(client, onyx); /* we try to read from register ONYX_REG_CONTROL * to check if the codec is present */ if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) { - i2c_detach_client(&onyx->i2c); printk(KERN_ERR PFX "failed to read control register\n"); goto fail; } @@ -1036,14 +1061,14 @@ static int onyx_create(struct i2c_adapter *adapter, onyx->codec.node = of_node_get(node); if (aoa_codec_register(&onyx->codec)) { - i2c_detach_client(&onyx->i2c); goto fail; } printk(KERN_DEBUG PFX "created and attached onyx instance\n"); return 0; fail: + i2c_set_clientdata(client, NULL); kfree(onyx); - return -EINVAL; + return -ENODEV; } static int onyx_i2c_attach(struct i2c_adapter *adapter) @@ -1080,28 +1105,33 @@ static int onyx_i2c_attach(struct i2c_adapter *adapter) return onyx_create(adapter, NULL, 0x47); } -static int onyx_i2c_detach(struct i2c_client *client) +static int onyx_i2c_remove(struct i2c_client *client) { - struct onyx *onyx = container_of(client, struct onyx, i2c); - int err; + struct onyx *onyx = i2c_get_clientdata(client); - if ((err = i2c_detach_client(client))) - return err; aoa_codec_unregister(&onyx->codec); of_node_put(onyx->codec.node); if (onyx->codec_info) kfree(onyx->codec_info); + i2c_set_clientdata(client, onyx); kfree(onyx); return 0; } +static const struct i2c_device_id onyx_i2c_id[] = { + { "aoa_codec_onyx", 0 }, + { } +}; + static struct i2c_driver onyx_driver = { .driver = { .name = "aoa_codec_onyx", .owner = THIS_MODULE, }, .attach_adapter = onyx_i2c_attach, - .detach_client = onyx_i2c_detach, + .probe = onyx_i2c_probe, + .remove = onyx_i2c_remove, + .id_table = onyx_i2c_id, }; static int __init onyx_init(void) diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index 008e0f8..f0ebc971 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -82,7 +82,7 @@ MODULE_DESCRIPTION("tas codec driver for snd-aoa"); struct tas { struct aoa_codec codec; - struct i2c_client i2c; + struct i2c_client *i2c; u32 mute_l:1, mute_r:1 , controls_created:1 , drc_enabled:1, @@ -108,9 +108,9 @@ static struct tas *codec_to_tas(struct aoa_codec *codec) static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data) { if (len == 1) - return i2c_smbus_write_byte_data(&tas->i2c, reg, *data); + return i2c_smbus_write_byte_data(tas->i2c, reg, *data); else - return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data); + return i2c_smbus_write_i2c_block_data(tas->i2c, reg, len, data); } static void tas3004_set_drc(struct tas *tas) @@ -882,12 +882,34 @@ static void tas_exit_codec(struct aoa_codec *codec) } -static struct i2c_driver tas_driver; - static int tas_create(struct i2c_adapter *adapter, struct device_node *node, int addr) { + struct i2c_board_info info; + struct i2c_client *client; + + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "aoa_codec_tas", I2C_NAME_SIZE); + info.addr = addr; + info.platform_data = node; + + client = i2c_new_device(adapter, &info); + if (!client) + return -ENODEV; + + /* + * Let i2c-core delete that device on driver removal. + * This is safe because i2c-core holds the core_lock mutex for us. + */ + list_add_tail(&client->detected, &client->driver->clients); + return 0; +} + +static int tas_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device_node *node = client->dev.platform_data; struct tas *tas; tas = kzalloc(sizeof(struct tas), GFP_KERNEL); @@ -896,17 +918,11 @@ static int tas_create(struct i2c_adapter *adapter, return -ENOMEM; mutex_init(&tas->mtx); - tas->i2c.driver = &tas_driver; - tas->i2c.adapter = adapter; - tas->i2c.addr = addr; + tas->i2c = client; + i2c_set_clientdata(client, tas); + /* seems that half is a saner default */ tas->drc_range = TAS3004_DRC_MAX / 2; - strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE); - - if (i2c_attach_client(&tas->i2c)) { - printk(KERN_ERR PFX "failed to attach to i2c\n"); - goto fail; - } strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN); tas->codec.owner = THIS_MODULE; @@ -915,14 +931,12 @@ static int tas_create(struct i2c_adapter *adapter, tas->codec.node = of_node_get(node); if (aoa_codec_register(&tas->codec)) { - goto detach; + goto fail; } printk(KERN_DEBUG "snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n", - addr, node->full_name); + (unsigned int)client->addr, node->full_name); return 0; - detach: - i2c_detach_client(&tas->i2c); fail: mutex_destroy(&tas->mtx); kfree(tas); @@ -970,14 +984,11 @@ static int tas_i2c_attach(struct i2c_adapter *adapter) return -ENODEV; } -static int tas_i2c_detach(struct i2c_client *client) +static int tas_i2c_remove(struct i2c_client *client) { - struct tas *tas = container_of(client, struct tas, i2c); - int err; + struct tas *tas = i2c_get_clientdata(client); u8 tmp = TAS_ACR_ANALOG_PDOWN; - if ((err = i2c_detach_client(client))) - return err; aoa_codec_unregister(&tas->codec); of_node_put(tas->codec.node); @@ -989,13 +1000,20 @@ static int tas_i2c_detach(struct i2c_client *client) return 0; } +static const struct i2c_device_id tas_i2c_id[] = { + { "aoa_codec_tas", 0 }, + { } +}; + static struct i2c_driver tas_driver = { .driver = { .name = "aoa_codec_tas", .owner = THIS_MODULE, }, .attach_adapter = tas_i2c_attach, - .detach_client = tas_i2c_detach, + .probe = tas_i2c_probe, + .remove = tas_i2c_remove, + .id_table = tas_i2c_id, }; static int __init tas_init(void) -- cgit v1.1 From 5de4155bb3760fc13a172c5cef2368ce218ebe1c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 20 Apr 2009 22:56:59 +0200 Subject: ALSA: keywest: Convert to new-style i2c driver The legacy i2c binding model is going away soon, so convert the ppc keywest sound driver to the new model or it will break. Signed-off-by: Jean Delvare Cc: Benjamin Herrenschmidt Signed-off-by: Takashi Iwai --- sound/ppc/keywest.c | 82 ++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) (limited to 'sound') diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 6ff99ed..a5afb26 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -33,26 +33,25 @@ static struct pmac_keywest *keywest_ctx; -static int keywest_attach_adapter(struct i2c_adapter *adapter); -static int keywest_detach_client(struct i2c_client *client); - -struct i2c_driver keywest_driver = { - .driver = { - .name = "PMac Keywest Audio", - }, - .attach_adapter = &keywest_attach_adapter, - .detach_client = &keywest_detach_client, -}; - - #ifndef i2c_device_name #define i2c_device_name(x) ((x)->name) #endif +static int keywest_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + i2c_set_clientdata(client, keywest_ctx); + return 0; +} + +/* + * This is kind of a hack, best would be to turn powermac to fixed i2c + * bus numbers and declare the sound device as part of platform + * initialization + */ static int keywest_attach_adapter(struct i2c_adapter *adapter) { - int err; - struct i2c_client *new_client; + struct i2c_board_info info; if (! keywest_ctx) return -EINVAL; @@ -60,46 +59,47 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) if (strncmp(i2c_device_name(adapter), "mac-io", 6)) return 0; /* ignored */ - new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (! new_client) - return -ENOMEM; - - new_client->addr = keywest_ctx->addr; - i2c_set_clientdata(new_client, keywest_ctx); - new_client->adapter = adapter; - new_client->driver = &keywest_driver; - new_client->flags = 0; - - strcpy(i2c_device_name(new_client), keywest_ctx->name); - keywest_ctx->client = new_client; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "keywest", I2C_NAME_SIZE); + info.addr = keywest_ctx->addr; + keywest_ctx->client = i2c_new_device(adapter, &info); - /* Tell the i2c layer a new client has arrived */ - if (i2c_attach_client(new_client)) { - snd_printk(KERN_ERR "tumbler: cannot attach i2c client\n"); - err = -ENODEV; - goto __err; - } - + /* + * Let i2c-core delete that device on driver removal. + * This is safe because i2c-core holds the core_lock mutex for us. + */ + list_add_tail(&keywest_ctx->client->detected, + &keywest_ctx->client->driver->clients); return 0; - - __err: - kfree(new_client); - keywest_ctx->client = NULL; - return err; } -static int keywest_detach_client(struct i2c_client *client) +static int keywest_remove(struct i2c_client *client) { + i2c_set_clientdata(client, NULL); if (! keywest_ctx) return 0; if (client == keywest_ctx->client) keywest_ctx->client = NULL; - i2c_detach_client(client); - kfree(client); return 0; } + +static const struct i2c_device_id keywest_i2c_id[] = { + { "keywest", 0 }, + { } +}; + +struct i2c_driver keywest_driver = { + .driver = { + .name = "PMac Keywest Audio", + }, + .attach_adapter = keywest_attach_adapter, + .probe = keywest_probe, + .remove = keywest_remove, + .id_table = keywest_i2c_id, +}; + /* exported */ void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c) { -- cgit v1.1 From bb023080fe72f1f80648e9b60771d9a94ce75aca Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Tue, 21 Apr 2009 07:35:25 +0200 Subject: ALSA: hda - Fix alc662_init_verbs Don't unmute unneeded amps for input mixers of ALC662 & co. It caused possible recording noises. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6ed787e..78bea2c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -15641,14 +15641,7 @@ static struct hda_verb alc662_init_verbs[] = { /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ /* Input mixer */ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* always trun on EAPD */ {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, -- cgit v1.1 From 622e84cdff719b9dcd3f495ddb0afb54995799cc Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Tue, 21 Apr 2009 07:39:04 +0200 Subject: ALSA: hda - Add quirks for Realtek codecs - Support ASUS F81Se F5Q P80 U20A U80 U50 UX50 for ALC269 - Support ASUS F70SL UX20 X58LE F50Z N80Vc N81Te N505Tp Vx3V N5051A for ALC663 - Support DELL ZM1 for ALC272 Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 98 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 78bea2c..c9300a3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -188,6 +188,8 @@ enum { ALC663_ASUS_MODE4, ALC663_ASUS_MODE5, ALC663_ASUS_MODE6, + ALC272_DELL, + ALC272_DELL_ZM1, ALC662_AUTO, ALC662_MODEL_LAST, }; @@ -12976,10 +12978,17 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", ALC269_ASUS_EEEPC_P703), + SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_EEEPC_P703), + SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_EEEPC_P703), + SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_EEEPC_P703), + SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_EEEPC_P703), + SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_EEEPC_P703), + SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_EEEPC_P703), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", ALC269_ASUS_EEEPC_P901), SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", ALC269_ASUS_EEEPC_P901), + SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_EEEPC_P901), SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), {} @@ -15210,12 +15219,23 @@ static hda_nid_t alc662_dac_nids[4] = { 0x02, 0x03, 0x04 }; +static hda_nid_t alc272_dac_nids[2] = { + 0x02, 0x03 +}; + static hda_nid_t alc662_adc_nids[1] = { /* ADC1-2 */ 0x09, }; +static hda_nid_t alc272_adc_nids[1] = { + /* ADC1-2 */ + 0x08, +}; + static hda_nid_t alc662_capsrc_nids[1] = { 0x22 }; +static hda_nid_t alc272_capsrc_nids[1] = { 0x23 }; + /* input MUX */ /* FIXME: should be a matrix-type input source selection */ @@ -15836,12 +15856,48 @@ static struct hda_verb alc662_ecs_init_verbs[] = { {} }; +static struct hda_verb alc272_dell_zm1_init_verbs[] = { + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)}, + {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, + {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {} +}; + +static struct hda_verb alc272_dell_init_verbs[] = { + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */ + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)}, + {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, + {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {} +}; + static struct snd_kcontrol_new alc662_auto_capture_mixer[] = { HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), { } /* end */ }; +static struct snd_kcontrol_new alc272_auto_capture_mixer[] = { + HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), + { } /* end */ +}; + static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec) { unsigned int present; @@ -16353,6 +16409,8 @@ static const char *alc662_models[ALC662_MODEL_LAST] = { static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS), + SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL), + SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1), SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), @@ -16365,26 +16423,36 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3), + SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA), + SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5), SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6), SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA), /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/ SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), + SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3), + SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V), /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/ SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA), SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4), SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG), @@ -16633,6 +16701,36 @@ static struct alc_config_preset alc662_presets[] = { .unsol_event = alc663_mode6_unsol_event, .init_hook = alc663_mode6_inithook, }, + [ALC272_DELL] = { + .mixers = { alc663_m51va_mixer }, + .cap_mixer = alc272_auto_capture_mixer, + .init_verbs = { alc662_init_verbs, alc272_dell_init_verbs }, + .num_dacs = ARRAY_SIZE(alc272_dac_nids), + .dac_nids = alc662_dac_nids, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), + .adc_nids = alc272_adc_nids, + .num_adc_nids = ARRAY_SIZE(alc272_adc_nids), + .capsrc_nids = alc272_capsrc_nids, + .channel_mode = alc662_3ST_2ch_modes, + .input_mux = &alc663_m51va_capture_source, + .unsol_event = alc663_m51va_unsol_event, + .init_hook = alc663_m51va_inithook, + }, + [ALC272_DELL_ZM1] = { + .mixers = { alc663_m51va_mixer }, + .cap_mixer = alc662_auto_capture_mixer, + .init_verbs = { alc662_init_verbs, alc272_dell_zm1_init_verbs }, + .num_dacs = ARRAY_SIZE(alc272_dac_nids), + .dac_nids = alc662_dac_nids, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), + .adc_nids = alc662_adc_nids, + .num_adc_nids = ARRAY_SIZE(alc662_adc_nids), + .capsrc_nids = alc662_capsrc_nids, + .channel_mode = alc662_3ST_2ch_modes, + .input_mux = &alc663_m51va_capture_source, + .unsol_event = alc663_m51va_unsol_event, + .init_hook = alc663_m51va_inithook, + }, }; -- cgit v1.1 From e10f9d87c9ac9fdfadb6305dbbc9052e49a02fdd Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 21 Apr 2009 15:17:54 +0200 Subject: [ALSA] ac97_codec: increase timeout for analog subsections On some hardware platforms, the AC97 codec requires more time to wake up. Signed-off-by: Jaroslav Kysela --- sound/pci/ac97/ac97_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 97ee127..78288db 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -2122,7 +2122,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, } /* nothing should be in powerdown mode */ snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0); - end_time = jiffies + msecs_to_jiffies(100); + end_time = jiffies + msecs_to_jiffies(120); do { if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) goto __ready_ok; -- cgit v1.1 From 30fd9940eee910d847f48bd8740b2d0eaa8d2cfc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 21 Apr 2009 15:30:31 +0200 Subject: [ALSA] intel8x0: another attempt to fix ac97_clock measure routine Appearently, a big delay ~300ms is required before hw is settled and ready to transfer samples on some hardware variants. Also, return back "clocking to 48000Hz" message when something fails. Signed-off-by: Jaroslav Kysela --- sound/pci/intel8x0.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 5dced5b..c4ba486 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2751,11 +2751,12 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) if (pos == 0) { snd_printk(KERN_ERR "intel8x0: measure - unreliable DMA position..\n"); __retry: - if (attempt < 2) { + if (attempt < 3) { + msleep(300); attempt++; goto __again; } - return; + goto __end; } pos /= 4; @@ -2782,6 +2783,7 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) else if (pos < 47500 || pos > 48500) /* not 48000Hz, tuning the clock.. */ chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos; + __end: printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock); snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0); } -- cgit v1.1 From 5bd3729f6818721f76a2a2f7d2ecad899bace340 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 21 Apr 2009 18:36:30 +0200 Subject: ALSA: hda - Add quirk for Packard Bell RS65 Added a quirk (model=m51va) for Packard Bell RS65 with ALC663. Reference: Novell bnc#496787 https://bugzilla.novell.com/show_bug.cgi?id=496787 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c9300a3..b8a0d3e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -16464,6 +16464,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), + SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA), SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0", ALC662_3ST_6ch_DIG), -- cgit v1.1 From 7315613f87f4aa0a52f60814f4ee3802e0bb1ec5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 23 Apr 2009 08:24:48 +0200 Subject: ALSA: hda - Fix init verbs of AD1884A mobile model The current ad1884a-mobile model has a problem that the speaker output doesn't work sometimes after boot or power-saving on some HP laptops. It seems that the verbs accessing to the non-functional widgets cause this problem. This patch simplifies the init verbs for mobile model not to touch unnecessary setups so that it avoids the speaker-mute problem. Reference: Novell bnc#495668 https://bugzilla.novell.com/show_bug.cgi?id=495668 Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 45 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 9bcd8ab..84cc49c 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3817,6 +3817,49 @@ static struct hda_verb ad1884a_laptop_verbs[] = { { } /* end */ }; +static struct hda_verb ad1884a_mobile_verbs[] = { + /* DACs; unmute as default */ + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ + /* Port-A (HP) mixer - route only from analog mixer */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + /* Port-A pin */ + {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + /* Port-A (HP) pin - always unmuted */ + {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* Port-B (mic jack) pin */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ + /* Port-C (int mic) pin */ + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */ + /* Port-F (int speaker) mixer - route only from analog mixer */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + /* Port-F pin */ + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Analog mixer; mute as default */ + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, + /* Analog Mix output amp */ + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* capture sources */ + /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* unsolicited event for pin-sense */ + {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, + { } /* end */ +}; + /* * Thinkpad X300 * 0x11 - HP @@ -3988,7 +4031,7 @@ static int patch_ad1884a(struct hda_codec *codec) break; case AD1884A_MOBILE: spec->mixers[0] = ad1884a_mobile_mixers; - spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs; + spec->init_verbs[0] = ad1884a_mobile_verbs; spec->multiout.dig_out_nid = 0; codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; codec->patch_ops.init = ad1884a_hp_init; -- cgit v1.1 From a9b487fa1e00b42f9667abfeca4a5295a71333db Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 27 Apr 2009 12:18:05 +0200 Subject: ALSA: snd-usb-caiaq: fix reported elapsed periods Reset the internal period position counter upon stream startup. This fixes initial aplay underruns and problems related to latency picky applications such as pulseaudio. Bumped the version number to 1.3.14. Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai --- sound/usb/caiaq/audio.c | 12 +++++++----- sound/usb/caiaq/device.c | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 3f45c0f..b13ce76 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -195,11 +195,14 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) debug("%s(%p)\n", __func__, substream); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dev->period_out_count[index] = BYTES_PER_SAMPLE + 1; dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1; - else + } else { + dev->period_in_count[index] = BYTES_PER_SAMPLE; dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE; - + } + if (dev->streaming) return 0; @@ -300,8 +303,7 @@ static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev, if (!sub) continue; - pb = frames_to_bytes(sub->runtime, - sub->runtime->period_size); + pb = snd_pcm_lib_period_bytes(sub); cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ? &dev->period_out_count[stream] : &dev->period_in_count[stream]; diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 6d51770..515de1c 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -35,7 +35,7 @@ #include "input.h" MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("caiaq USB audio, version 1.3.13"); +MODULE_DESCRIPTION("caiaq USB audio, version 1.3.14"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," "{Native Instruments, RigKontrol3}," -- cgit v1.1 From 395a434e39cb6dc6e1ff53bb43722b534a3c68d6 Mon Sep 17 00:00:00 2001 From: Subrata Modak Date: Mon, 27 Apr 2009 16:42:37 +0530 Subject: ALSA: Fix Trivial Warnining in sound/pci/cmipci.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed the compile warning below by initializatin iomidi variable properly. sound/pci/cmipci.c: In function ‘snd_cmipci_probe’: sound/pci/cmipci.c:3017: warning: ‘iomidi’ may be used uninitialized in this function Signed-off-by: Subrata Modak Cc: linux-pci Cc: Balbir Singh Cc: Sachin P Sant Signed-off-by: Takashi Iwai --- sound/pci/cmipci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index c7899c3..449fe02 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -3014,7 +3014,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc .dev_free = snd_cmipci_dev_free, }; unsigned int val; - long iomidi; + long iomidi = 0; int integrated_midi = 0; char modelstr[16]; int pcm_index, pcm_spdif_index; -- cgit v1.1 From 2008f137e92220b98120c4803499cdddb2b0fb06 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 28 Apr 2009 12:25:59 +0200 Subject: ALSA: Add missing SNDRV_PCM_INFO_BATCH flag to some drivers Added SNDRV_PCM_INFO_BATCH flag to PCM info field of some drivers that really don't give the precise pointer value. Signed-off-by: Takashi Iwai --- sound/isa/msnd/msnd.c | 6 ++++-- sound/pci/bt87x.c | 6 ++++-- sound/pci/korg1212/korg1212.c | 6 ++++-- sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 3 ++- sound/soc/au1x/dbdma2.c | 2 +- sound/soc/fsl/mpc5200_psc_i2s.c | 3 ++- sound/soc/sh/dma-sh7760.c | 3 ++- sound/sparc/dbri.c | 3 ++- sound/usb/usx2y/usbusx2yaudio.c | 3 ++- 9 files changed, 23 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c index 9064544..3a1526a 100644 --- a/sound/isa/msnd/msnd.c +++ b/sound/isa/msnd/msnd.c @@ -438,7 +438,8 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, static struct snd_pcm_hardware snd_msnd_playback = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_8000_48000, .rate_min = 8000, @@ -456,7 +457,8 @@ static struct snd_pcm_hardware snd_msnd_playback = { static struct snd_pcm_hardware snd_msnd_capture = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_8000_48000, .rate_min = 8000, diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index a299340..ce3f2e9 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -349,7 +349,8 @@ static struct snd_pcm_hardware snd_bt87x_digital_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = 0, /* set at runtime */ .channels_min = 2, @@ -365,7 +366,8 @@ static struct snd_pcm_hardware snd_bt87x_analog_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, .rates = SNDRV_PCM_RATE_KNOT, .rate_min = ANALOG_CLOCK / CLOCK_DIV_MAX, diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 8b79969..7cc38a1 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -1238,7 +1238,8 @@ static struct snd_pcm_hardware snd_korg1212_playback_info = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED), + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BATCH), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000), @@ -1258,7 +1259,8 @@ static struct snd_pcm_hardware snd_korg1212_capture_info = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED), + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BATCH), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000), diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 01066c9..d057e64 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -240,7 +240,8 @@ static int pdacf_pcm_prepare(struct snd_pcm_substream *subs) static struct snd_pcm_hardware pdacf_pcm_capture_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH), .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE, diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 30490a2..594c6c5 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -82,7 +82,7 @@ static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2]; /* PCM hardware DMA capabilities - platform specific */ static const struct snd_pcm_hardware au1xpsc_pcm_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED, + SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH, .formats = AU1XPSC_PCM_FMTS, .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES, .period_bytes_max = 4096 * 1024 - 1, diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 3aa729d..1111c71 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -504,7 +504,8 @@ static struct snd_soc_dai psc_i2s_dai_template = { static const struct snd_pcm_hardware psc_i2s_pcm_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER, + SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE, .rate_min = 8000, diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index 0dad3a0..baddb12 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c @@ -103,7 +103,8 @@ static struct snd_pcm_hardware camelot_pcm_hardware = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH), .formats = DMABRG_FMTS, .rates = DMABRG_RATES, .rate_min = 8000, diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index af95ff1..1d2e51b 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -1975,7 +1975,8 @@ static struct snd_pcm_hardware snd_dbri_pcm_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_U8 | diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 9a608fa..dd1ab61 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -870,7 +870,8 @@ static struct snd_pcm_hardware snd_usX2Y_2c = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH), .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE, .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, .rate_min = 44100, -- cgit v1.1 From 3e5b50165fd0be080044586f43fcdd460ed27610 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 28 Apr 2009 12:07:08 +0200 Subject: ALSA: pcm core - Avoid jiffies check for devices with BATCH flag The hardware devices with SNDRV_PCM_INFO_BATCH flag can't give the precise current position. And such hardwares have often big FIFO in addition to the ring buffer, and it screws up the jiffies check in pcm_lib.c. This patch adds a simple check of info flag so that the driver skips the jiffies check in snd_pcm_period_elapsed() when BATCH flag is set. Signed-off-by: Takashi Iwai --- sound/core/pcm_lib.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sound') diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 63d088f..a2a792c 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -249,6 +249,12 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) new_hw_ptr = hw_base + pos; } } + /* Skip the jiffies check for hardwares with BATCH flag. + * Such hardware usually just increases the position at each IRQ, + * thus it can't give any strange position. + */ + if (runtime->hw.info & SNDRV_PCM_INFO_BATCH) + goto no_jiffies_check; hdelta = new_hw_ptr - old_hw_ptr; jdelta = jiffies - runtime->hw_ptr_jiffies; if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { @@ -272,6 +278,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) hw_base -= hw_base % runtime->buffer_size; delta = 0; } + no_jiffies_check: if (delta > runtime->period_size + runtime->period_size / 2) { hw_ptr_error(substream, "Lost interrupts? " -- cgit v1.1 From 6574612fbb34c63117581e68f2231ddce027e41e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 4 May 2009 16:03:21 +0200 Subject: ASoC: Remove BROKEN from mpc5200 kconfig The regression was fixed by commit 3e5b50165fd0be080044586f43fcdd460ed27610, so no need to mark this driver as BROKEN. Signed-off-by: Takashi Iwai --- sound/soc/fsl/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index e7dd79a..9fc9082 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -21,7 +21,7 @@ config SND_SOC_MPC8610_HPCD config SND_SOC_MPC5200_I2S tristate "Freescale MPC5200 PSC in I2S mode driver" - depends on PPC_MPC52xx && PPC_BESTCOMM && BROKEN + depends on PPC_MPC52xx && PPC_BESTCOMM select SND_SOC_OF_SIMPLE select PPC_BESTCOMM_GEN_BD help -- cgit v1.1